home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 2 / ETO Development Tools 2.iso / Tools - Objects / MacApp / MacApp CD Release / MacApp 2.0.1 (Many Libraries) / Libraries / UInspector.inc1.p < prev    next >
Encoding:
Text File  |  1990-10-25  |  66.6 KB  |  2,495 lines  |  [TEXT/MPS ]

  1. {$P}
  2. {[a-,body+,h-,o=100,r+,rec+,t=4,u+,#+,j=20/57/1$,n-]}
  3. {UInspector.inc1.p}
  4. {Copyright © 1987-1990 by Apple Computer, Inc.    All rights reserved.}
  5.  
  6. {$IFC NOT qDebugTheDebugger}
  7. {$W+}
  8. {$R-}
  9. {$Init-}
  10. {$OV-}
  11. {$ENDC}
  12. {$IFC qNames}
  13. {$D+}
  14. {$ENDC}
  15.  
  16. CONST
  17.     kInspectorWindowType = 900;
  18.     bInternalString     = - 500;                        { used to id strings used internal to
  19.                                                          inspector }
  20.  
  21. TYPE
  22.  
  23.     {$IFC qHasForward}
  24.     TInspectWindow        = OBJECT;    FORWARD;
  25.     TObjListView        = OBJECT;    FORWARD;
  26.     TObjectView            = OBJECT;    FORWARD;
  27.     TClassListView        = OBJECT;    FORWARD;
  28.     {$EndC}
  29.  
  30.     TObjectList         = OBJECT (TList)                { Will just be ordered by object id }
  31.  
  32.         PROCEDURE TObjectList.IObjectList(classId: ObjClassID);
  33.  
  34.         PROCEDURE TObjectList.AddObject(theObject: TObject);
  35.  
  36.         PROCEDURE TObjectList.RemoveObject(theObject: TObject);
  37.  
  38.         PROCEDURE TObjectList.Fields(PROCEDURE DoToField(fieldName: Str255;
  39.                                                          fieldAddr: Ptr;
  40.                                                          fieldType: INTEGER)); OVERRIDE;
  41.  
  42.         END;
  43.  
  44.     TClassesByID        = OBJECT (TSortedList)
  45.  
  46.         PROCEDURE TClassesByID.IClassesByID;
  47.  
  48.         FUNCTION TClassesByID.Compare(item1, item2: TObject): INTEGER; OVERRIDE;
  49.  
  50.         PROCEDURE TClassesByID.Fields(PROCEDURE DoToField(fieldName: Str255;
  51.                                                         fieldAddr: Ptr;
  52.                                                         fieldType: INTEGER)); OVERRIDE;
  53.  
  54.         END;
  55.  
  56.     TClassesByName        = OBJECT (TSortedList)
  57.  
  58.         PROCEDURE TClassesByName.IClassesByName;
  59.  
  60.         FUNCTION TClassesByName.Compare(item1, item2: TObject): INTEGER; OVERRIDE;
  61.  
  62.         PROCEDURE TClassesByName.Fields(PROCEDURE DoToField(fieldName: Str255;
  63.                                                         fieldAddr: Ptr;
  64.                                                         fieldType: INTEGER)); OVERRIDE;
  65.  
  66.         END;
  67.  
  68.     TInspector            = OBJECT (TDocument)
  69.  
  70.         fClassesByID:        TClassesByID;
  71.         fClassesByName:     TClassesByName;
  72.         fWindowCount:        INTEGER;
  73.         fStaggerCount:        INTEGER;
  74.  
  75.         PROCEDURE TInspector.IInspector;
  76.  
  77.         PROCEDURE TInspector.Free; OVERRIDE;
  78.  
  79.         FUNCTION TInspector.MakeWindow: TInspectWindow;
  80.  
  81.         FUNCTION TInspector.AddObjectList(classId: ObjClassID): TObjectList;
  82.  
  83.         FUNCTION TInspector.GetObjectList(classId: ObjClassID): TObjectList;
  84.  
  85.         PROCEDURE TInspector.AddObject(theObject: TObject);
  86.  
  87.         PROCEDURE TInspector.RemoveObject(theObject: TObject);
  88.  
  89.         PROCEDURE TInspector.DoSetupMenus; OVERRIDE;
  90.  
  91.         PROCEDURE TInspector.Fields(PROCEDURE DoToField(fieldName: Str255;
  92.                                                         fieldAddr: Ptr;
  93.                                                         fieldType: INTEGER)); OVERRIDE;
  94.  
  95.         END;
  96.  
  97.     TInspectWindow        = OBJECT (TWindow)
  98.  
  99.         fClassListView:     TClassListView;
  100.         fObjListView:        TObjListView;
  101.         fObjectView:        TObjectView;
  102.  
  103.         PROCEDURE TInspectWindow.IRes(itsDocument: TDocument;
  104.                                       itsSuperView: TView;
  105.                                       VAR itsParams: Ptr); OVERRIDE;
  106.         PROCEDURE TInspectWindow.IInspectWindow;
  107.  
  108.         PROCEDURE TInspectWindow.Draw(area: Rect); OVERRIDE;
  109.  
  110.         PROCEDURE TInspectWindow.CloseByUser; OVERRIDE;
  111.  
  112.         PROCEDURE TInspectWindow.InsertClass(itemNo: INTEGER);
  113.  
  114.         PROCEDURE TInspectWindow.Resize(width, height: VCoordinate;
  115.                                         invalidate: BOOLEAN); OVERRIDE;
  116.  
  117.         PROCEDURE TInspectWindow.SetNumberOfClasses(noOfClasses: INTEGER);
  118.  
  119.         PROCEDURE TInspectWindow.SetTitleForDoc(newDocTitle: Str255); OVERRIDE;
  120.  
  121.         PROCEDURE TInspectWindow.SelectObject(theObject: TObject;
  122.                                               theType: INTEGER);
  123.  
  124.         PROCEDURE TInspectWindow.Fields(PROCEDURE DoToField(fieldName: Str255;
  125.                                                             fieldAddr: Ptr;
  126.                                                             fieldType: INTEGER)); OVERRIDE;
  127.  
  128.         END;
  129.  
  130.     TListView            = OBJECT (TView)
  131.  
  132.         fCurrentSelection:    INTEGER;                    { index of the current selection, if any,
  133.                                                          otherwise 0 }
  134.         fNumberOfItems:     INTEGER;                    { number of items currently in the list }
  135.         fTextStyle:         TextStyle;                    { font characteristics }
  136.         fItemHeight:        INTEGER;                    { height of each item including leading }
  137.         fLineAscent:        INTEGER;                    { position of baseline relative to top of
  138.                                                          line }
  139.  
  140.         PROCEDURE TListView.IRes(itsDocument: TDocument;
  141.                                  itsSuperView: TView;
  142.                                  VAR itsParams: Ptr); OVERRIDE;
  143.         PROCEDURE TListView.IListView(itsDocument: TDocument;
  144.                                       itsSuperView: TView;
  145.                                       itsLocation: VPoint;
  146.                                       itsSize: VPoint;
  147.                                       itsTextStyle: TextStyle;
  148.                                       itsNumberOfItems: INTEGER;
  149.                                       itsHSizeDet: SizeDeterminer);
  150.  
  151.         PROCEDURE TListView.CalcMinSize(VAR minSize: VPoint); OVERRIDE;
  152.  
  153.         PROCEDURE TListView.ChangeSelection(index: INTEGER;
  154.                                             highlight: BOOLEAN);
  155.  
  156.         PROCEDURE TListView.DoHighlightSelection(fromHL, toHL: HLState); OVERRIDE;
  157.  
  158.         FUNCTION TListView.DoMouseCommand(VAR theMouse: Point;
  159.                                           VAR info: EventInfo;
  160.                                           VAR hysteresis: Point): TCommand; OVERRIDE;
  161.  
  162.         PROCEDURE TListView.Draw(area: Rect); OVERRIDE;
  163.  
  164.         PROCEDURE TListView.DrawItem(itemNumber: INTEGER;
  165.                                      basePoint: Point);
  166.  
  167.         PROCEDURE TListView.Fields(PROCEDURE DoToField(fieldName: Str255;
  168.                                                        fieldAddr: Ptr;
  169.                                                        fieldType: INTEGER)); OVERRIDE;
  170.  
  171.         PROCEDURE TListView.InsertItem(itemNo: INTEGER);
  172.  
  173.         PROCEDURE TListView.DeleteItem(itemNo: INTEGER);
  174.  
  175.         PROCEDURE TListView.ItemToVRect(index: INTEGER;
  176.                                         VAR itemRect: VRect);
  177.  
  178.         PROCEDURE TListView.RevealItem(itemNumber: INTEGER);
  179.  
  180.         PROCEDURE TListView.SelectItem(itemNumber: INTEGER);
  181.  
  182.         PROCEDURE TListView.SetStyle(itsTextStyle: TextStyle);
  183.  
  184.         PROCEDURE TListView.SetNumberOfItems(numberOfItems: INTEGER);
  185.  
  186.         PROCEDURE TListView.SetPen;
  187.  
  188.         FUNCTION TListView.VPointToItem(thePoint: VPoint): INTEGER;
  189.  
  190.         END;
  191.  
  192.     TClassListView        = OBJECT (TListView)            {Upper-left view}
  193.  
  194.         fInspectWindow:     TInspectWindow;
  195.  
  196.         PROCEDURE TClassListView.IRes(itsDocument: TDocument;
  197.                                       itsSuperView: TView;
  198.                                       VAR itsParams: Ptr); OVERRIDE;
  199.  
  200.         PROCEDURE TClassListView.IClassListView(itsWindow: TInspectWindow;
  201.                                                 itsLocation: VPoint;
  202.                                                 itsSize: VPoint);
  203.  
  204.         PROCEDURE TClassListView.DrawItem(itemNumber: INTEGER;
  205.                                           basePoint: Point); OVERRIDE;
  206.  
  207.         PROCEDURE TClassListView.SelectItem(itemNumber: INTEGER); OVERRIDE;
  208.  
  209.         PROCEDURE TClassListView.Fields(PROCEDURE DoToField(fieldName: Str255;
  210.                                                             fieldAddr: Ptr;
  211.                                                             fieldType: INTEGER)); OVERRIDE;
  212.  
  213.         END;
  214.  
  215.     TObjListView        = OBJECT (TListView)            {Upper-right view}
  216.  
  217.         fInspectWindow:     TInspectWindow;
  218.         fObjectList:        TObjectList;
  219.  
  220.         PROCEDURE TObjListView.IRes(itsDocument: TDocument;
  221.                                     itsSuperView: TView;
  222.                                     VAR itsParams: Ptr); OVERRIDE;
  223.  
  224.         PROCEDURE TObjListView.IObjListView(itsWindow: TInspectWindow;
  225.                                             itsLocation: VPoint;
  226.                                             itsSize: VPoint);
  227.  
  228.         PROCEDURE TObjListView.InstallObjectList(theObjectList: TObjectList);
  229.  
  230.         PROCEDURE TObjListView.DrawItem(itemNumber: INTEGER;
  231.                                         basePoint: Point); OVERRIDE;
  232.  
  233.         PROCEDURE TObjListView.SelectItem(itemNumber: INTEGER); OVERRIDE;
  234.  
  235.         PROCEDURE TObjListView.Fields(PROCEDURE DoToField(fieldName: Str255;
  236.                                                           fieldAddr: Ptr;
  237.                                                           fieldType: INTEGER)); OVERRIDE;
  238.  
  239.         END;
  240.  
  241.     TObjectView         = OBJECT (TListView)            {bottom view}
  242.  
  243.         fInspectWindow:     TInspectWindow;
  244.         fObject:            TObject;
  245.         fType:                INTEGER;
  246.         fLockState:         BOOLEAN;
  247.  
  248.         PROCEDURE TObjectView.IRes(itsDocument: TDocument;
  249.                                    itsSuperView: TView;
  250.                                    VAR itsParams: Ptr); OVERRIDE;
  251.  
  252.         PROCEDURE TObjectView.IObjectView(itsWindow: TInspectWindow;
  253.                                           itsLocation: VPoint;
  254.                                           itsSize: VPoint);
  255.  
  256.         PROCEDURE TObjectView.InspectControlHandle(PROCEDURE
  257.                                                    InspectField(fieldName: StringPtr;
  258.                                                                 fieldAddr: Ptr;
  259.                                                                 fieldType: INTEGER));
  260.  
  261.         PROCEDURE TObjectView.InspectGrafPtr(PROCEDURE
  262.                                              InspectField(fieldName: StringPtr;
  263.                                                           fieldAddr: Ptr;
  264.                                                           fieldType: INTEGER));
  265.  
  266.         PROCEDURE TObjectView.InspectRgnHandle(PROCEDURE
  267.                                                InspectField(fieldName: StringPtr;
  268.                                                             fieldAddr: Ptr;
  269.                                                             fieldType: INTEGER));
  270.  
  271.         PROCEDURE TObjectView.InspectTEHandle(PROCEDURE
  272.                                               InspectField(fieldName: StringPtr;
  273.                                                            fieldAddr: Ptr;
  274.                                                            fieldType: INTEGER));
  275.  
  276.         PROCEDURE TObjectView.InspectWindowPtr(PROCEDURE
  277.                                                InspectField(fieldName: StringPtr;
  278.                                                             fieldAddr: Ptr;
  279.                                                             fieldType: INTEGER));
  280.  
  281.         PROCEDURE TObjectView.InspectHandle(PROCEDURE
  282.                                             InspectField(fieldName: StringPtr;
  283.                                                          fieldAddr: Ptr;
  284.                                                          fieldType: INTEGER));
  285.  
  286.         PROCEDURE TObjectView.LockObject;
  287.  
  288.         PROCEDURE TObjectView.UnlockObject;
  289.  
  290.         PROCEDURE TObjectView.ChangeSelection(index: INTEGER;
  291.                                               highlight: BOOLEAN); OVERRIDE;
  292.  
  293.         PROCEDURE TObjectView.SelectField(index: INTEGER;
  294.                                           inspectWindow: TInspectWindow);
  295.  
  296.         FUNCTION TObjectView.DoMouseCommand(VAR theMouse: Point;
  297.                                             VAR info: EventInfo;
  298.                                             VAR hysteresis: Point): TCommand; OVERRIDE;
  299.  
  300.         PROCEDURE TObjectView.Draw(area: Rect); OVERRIDE;
  301.  
  302.         PROCEDURE TObjectView.SuperViewChangedSize(delta: VPoint;
  303.                                              invalidate: BOOLEAN); OVERRIDE;
  304.  
  305.         PROCEDURE TObjectView.Resize(width, height: VCoordinate;
  306.                                      invalidate: BOOLEAN); OVERRIDE;
  307.  
  308.         PROCEDURE TObjectView.FirstFieldThat(FUNCTION
  309.                                              TestField(fieldName: StringPtr;
  310.                                                        fieldAddr: Ptr;
  311.                                                        fieldType: INTEGER): BOOLEAN);
  312.  
  313.         PROCEDURE TObjectView.InstallObject(theObject: TObject;
  314.                                             theObjectType: INTEGER);
  315.  
  316.         PROCEDURE TObjectView.Fields(PROCEDURE DoToField(fieldName: Str255;
  317.                                                          fieldAddr: Ptr;
  318.                                                          fieldType: INTEGER)); OVERRIDE;
  319.  
  320.         END;
  321.  
  322. VAR
  323.     {$Push} {$Z+}                                        { Make the root of the inspector visible to
  324.                                                          selected friends }
  325.     pInspector:         TInspector;
  326.     {$Pop}
  327.     pInspectorStyle:    TextStyle;
  328.     pSavedFocus:        FocusRec;
  329.  
  330.     {$IFC qTrace} {$D+} {$ENDC}                         { Turn off tracing for all Inspector code in
  331.                                                          this file }
  332.     {$S MAInspector}                                    { Everything goes in here }
  333.  
  334.     {---------------------------------------------------------------------------}
  335.  
  336.     {$Push}
  337.     {$IFC qTrace}
  338.     {$IFC qDebugTheDebugger}
  339.     {$D++}
  340.     {$ENDC}
  341.     {$ENDC}
  342.  
  343. PROCEDURE AddObjectToInspector(theObject: TObject);
  344.  {This is called from %_OBNEW when an object is created, and from
  345.   TObject.ShallowClone when cloning an object.}
  346.  
  347.     BEGIN
  348.     IF pInspector <> NIL THEN
  349.         pInspector.AddObject(theObject);
  350.     END;
  351. {$Pop}
  352.  
  353. {---------------------------------------------------------------------------}
  354.  
  355. PROCEDURE InitUInspector;
  356.  
  357.     BEGIN
  358.     pInspector := NIL;
  359.     SetTextStyle(pInspectorStyle, applFont, [], 9, gRGBBlack);
  360.     pSavedFocus.clip := NewRgn;
  361.     FailNIL(pSavedFocus.clip);
  362.  
  363.     IF qTemplateViews THEN
  364.         BEGIN
  365.         { Make sure linker doesn't dead strip these }
  366.         IF gDeadStripSuppression THEN
  367.             BEGIN
  368.             IF Member(TObject(NIL), TInspectWindow) THEN;
  369.             IF Member(TObject(NIL), TClassListView) THEN;
  370.             IF Member(TObject(NIL), TObjListView) THEN;
  371.             IF Member(TObject(NIL), TObjectView) THEN;
  372.             END;
  373.         END;
  374.  
  375.     END;
  376.  
  377. {---------------------------------------------------------------------------}
  378.  
  379. PROCEDURE MakeInspector;
  380.  
  381.     VAR
  382.         anInspector:        TInspector;
  383.         wasAddNewObjectsToInspector: BOOLEAN;
  384.         wasTrcEnable:        BOOLEAN;
  385.  
  386.     BEGIN
  387.     {$IFC NOT qDebugTheDebugger}
  388.     {$IFC qDebug}
  389.     wasTrcEnable := TrcEnable(False);
  390.     {$EndC}
  391.     wasAddNewObjectsToInspector := AddNewObjectsToInspector(False);
  392.     {$ENDC}
  393.  
  394.     { Allocate and initialize the document}
  395.     New(anInspector);
  396.     FailNIL(anInspector);
  397.     anInspector.IInspector;
  398.  
  399.     {$IFC NOT qDebugTheDebugger}
  400.     IF AddNewObjectsToInspector(wasAddNewObjectsToInspector) THEN;
  401.     {$IFC qDebug}
  402.     IF TrcEnable(wasTrcEnable) THEN;
  403.     {$EndC}
  404.     {$ENDC}
  405.     END;
  406.  
  407. {---------------------------------------------------------------------------}
  408.  
  409. PROCEDURE MakeInspectorWindow;
  410.  
  411.     VAR
  412.         wasAddNewObjectsToInspector: BOOLEAN;
  413.         wasTrcEnable:        BOOLEAN;
  414.         anInspectWindow:    TInspectWindow;
  415.  
  416.     BEGIN
  417.     {$IFC NOT qDebugTheDebugger}
  418.     {$IFC qDebug}
  419.     wasTrcEnable := TrcEnable(False);
  420.     {$EndC}
  421.     wasAddNewObjectsToInspector := AddNewObjectsToInspector(False);
  422.     {$ENDC}
  423.  
  424.     IF pInspector <> NIL THEN
  425.         BEGIN
  426.         anInspectWindow := pInspector.MakeWindow;
  427.         anInspectWindow.Open;
  428.         END;
  429.  
  430.     {$IFC NOT qDebugTheDebugger}
  431.     IF AddNewObjectsToInspector(wasAddNewObjectsToInspector) THEN;
  432.     {$IFC qDebug}
  433.     IF TrcEnable(wasTrcEnable) THEN;
  434.     {$EndC}
  435.     {$ENDC}
  436.     END;
  437.  
  438. {---------------------------------------------------------------------------}
  439.  
  440. {$Push}
  441. {$IFC qTrace}
  442. {$IFC qDebugTheDebugger}
  443. {$D++}
  444. {$ENDC}
  445. {$ENDC}
  446.  
  447. PROCEDURE RemoveObjectFromInspector(theObject: TObject);
  448. {Called from TObject.Free.}
  449.  
  450.     VAR
  451.         wasAddNewObjectsToInspector: BOOLEAN;
  452.         wasTrcEnable:        BOOLEAN;
  453.  
  454.     BEGIN
  455.     {$IFC NOT qDebugTheDebugger}
  456.     {$IFC qDebug}
  457.     wasTrcEnable := TrcEnable(False);
  458.     {$EndC}
  459.     wasAddNewObjectsToInspector := AddNewObjectsToInspector(False);
  460.     {$ENDC}
  461.     IF NOT gAppDone THEN
  462.         IF pInspector <> NIL THEN
  463.             pInspector.RemoveObject(theObject);
  464.     {$IFC NOT qDebugTheDebugger}
  465.     IF AddNewObjectsToInspector(wasAddNewObjectsToInspector) THEN;
  466.     {$IFC qDebug}
  467.     IF TrcEnable(wasTrcEnable) THEN;
  468.     {$EndC}
  469.     {$ENDC}
  470.     END;
  471. {$Pop}
  472.  
  473. {---------------------------------------------------------------------------}
  474.  
  475. PROCEDURE TObjectList.IObjectList(classId: ObjClassID);
  476.  
  477.     BEGIN
  478.     IList;
  479.     SetEltTypeID(classId);
  480.     END;
  481.  
  482. {---------------------------------------------------------------------------}
  483.  
  484. PROCEDURE TObjectList.AddObject(theObject: TObject);
  485.  
  486.     BEGIN
  487.     {$IFC qDebugTheDebugger}
  488.     IF GetClassID(theObject) <> fObjClassId THEN
  489.         ProgramBreak('TObjectList.AddObject: Object of wrong class');
  490.     {$ENDC}
  491.  
  492.     Insert(theObject);
  493.     END;
  494.  
  495. {---------------------------------------------------------------------------}
  496.  
  497. PROCEDURE TObjectList.Fields(PROCEDURE DoToField(fieldName: Str255;
  498.                                                  fieldAddr: Ptr;
  499.                                                  fieldType: INTEGER)); OVERRIDE;
  500.  
  501.     BEGIN
  502.     DoToField('TObjectList', NIL, bClass);
  503.  
  504.     INHERITED Fields(DoToField);
  505.     END;
  506.  
  507. {---------------------------------------------------------------------------}
  508.  
  509. PROCEDURE TObjectList.RemoveObject(theObject: TObject);
  510.  
  511.     BEGIN
  512.     {$IFC qDebugTheDebugger}
  513.     IF GetClassID(theObject) <> fObjClassId THEN
  514.         ProgramBreak('TObjectList.RemoveObject: Object of wrong class');
  515.     {$ENDC}
  516.  
  517.     Delete(theObject);
  518.     END;
  519.  
  520. {---------------------------------------------------------------------------}
  521.  
  522. PROCEDURE TClassesByID.IClassesByID;
  523.  
  524.     BEGIN
  525.     ISortedList;
  526.     END;
  527.  
  528. {---------------------------------------------------------------------------}
  529.  
  530. FUNCTION TClassesByID.Compare(item1, item2: TObject): INTEGER; OVERRIDE;
  531.  
  532.     BEGIN
  533.     IF TObjectList(item1).fObjClassId < TObjectList(item2).fObjClassId THEN
  534.         Compare := kItem1LessThanItem2
  535.     ELSE IF TObjectList(item1).fObjClassId > TObjectList(item2).fObjClassId THEN
  536.         Compare := kItem1GreaterThanItem2
  537.     ELSE
  538.         Compare := kItem1EqualItem2;
  539.     END;
  540.  
  541. {---------------------------------------------------------------------------}
  542.  
  543. PROCEDURE TClassesByID.Fields(PROCEDURE DoToField(fieldName: Str255;
  544.                                                 fieldAddr: Ptr;
  545.                                                 fieldType: INTEGER)); OVERRIDE;
  546.     BEGIN
  547.     DoToField('TClassesByID', NIL, bClass);
  548.     INHERITED Fields(DoToField);
  549.     END;
  550.  
  551. {---------------------------------------------------------------------------}
  552.  
  553. PROCEDURE TClassesByName.IClassesByName;
  554.  
  555.     BEGIN
  556.     ISortedList;
  557.     END;
  558.  
  559. {---------------------------------------------------------------------------}
  560.  
  561. FUNCTION TClassesByName.Compare(item1, item2: TObject): INTEGER; OVERRIDE;
  562.  
  563.     VAR
  564.         string1, string2:    MAName;
  565.  
  566.     BEGIN
  567.     GetClassNameFromID(TObjectList(item1).fObjClassId, string1);
  568.     GetClassNameFromID(TObjectList(item2).fObjClassId, string2);
  569.     IF string1 < string2 THEN
  570.         Compare := kItem1LessThanItem2
  571.     ELSE IF string1 > string2 THEN
  572.         Compare := kItem1GreaterThanItem2
  573.     ELSE
  574.         Compare := kItem1EqualItem2;
  575.     END;
  576.  
  577. {---------------------------------------------------------------------------}
  578.  
  579. PROCEDURE TClassesByName.Fields(PROCEDURE DoToField(fieldName: Str255;
  580.                                                 fieldAddr: Ptr;
  581.                                                 fieldType: INTEGER)); OVERRIDE;
  582.     BEGIN
  583.     DoToField('TClassesByName', NIL, bClass);
  584.     INHERITED Fields(DoToField);
  585.     END;
  586.  
  587. {---------------------------------------------------------------------------}
  588.  
  589. PROCEDURE TInspector.IInspector;
  590.  
  591.     VAR
  592.         aClassesByName:     TClassesByName;
  593.         aClassesById:        TClassesByID;
  594.  
  595.     BEGIN
  596.     IDocument('????', '????', NOT kUsesDataFork, NOT kUsesRsrcFork, NOT kDataOpen, NOT kRsrcOpen);
  597.     SetTitle('Inspector');
  598.  
  599.     New(aClassesByName);
  600.     FailNIL(aClassesByName);
  601.     aClassesByName.IClassesByName;
  602.     aClassesByName.SetEltType('TObjectList');
  603.     fClassesByName := aClassesByName;
  604.     New(aClassesById);
  605.     FailNIL(aClassesById);
  606.     aClassesById.IClassesByID;
  607.     aClassesById.SetEltType('TObjectList');
  608.     fClassesByID := aClassesById;
  609.  
  610.     pInspector := SELF;
  611.  
  612.     fWindowCount := 0;
  613.     fStaggerCount := 0;
  614.     END;
  615.  
  616. {---------------------------------------------------------------------------}
  617.  
  618. PROCEDURE TInspector.Free; OVERRIDE;
  619.  
  620.     BEGIN
  621.  
  622.     fClassesByID := TClassesByID(FreeListIfObject(fClassesByID));
  623.  
  624.     FreeIfObject(fClassesByName);
  625.     fClassesByName := NIL;
  626.  
  627.     pInspector := NIL;
  628.  
  629.     INHERITED Free;
  630.     END;
  631.  
  632. {---------------------------------------------------------------------------}
  633.  
  634. PROCEDURE TInspector.Fields(PROCEDURE DoToField(fieldName: Str255;
  635.                                                 fieldAddr: Ptr;
  636.                                                 fieldType: INTEGER)); OVERRIDE;
  637.  
  638.     BEGIN
  639.     DoToField('TInspector', NIL, bClass);
  640.     DoToField('fClassesByID', @fClassesByID, bObject);
  641.     DoToField('fClassesByName', @fClassesByName, bObject);
  642.     DoToField('fWindowCount', @fWindowCount, bInteger);
  643.     DoToField('fStaggerCount', @fStaggerCount, bInteger);
  644.     INHERITED Fields(DoToField);
  645.     END;
  646.  
  647. {---------------------------------------------------------------------------}
  648.  
  649. FUNCTION TInspector.MakeWindow: TInspectWindow;
  650.  
  651.     VAR
  652.         anInspectWindow:    TInspectWindow;
  653.         staggerCount:        INTEGER;
  654.         screenRect:         Rect;
  655.  
  656.     BEGIN
  657.     fWindowCount := fWindowCount + 1;
  658.  
  659.     IF qTemplateViews THEN
  660.         BEGIN
  661.         anInspectWindow := TInspectWindow(NewTemplateWindow(kInspectorWindowType, SELF));
  662.         FailNIL(anInspectWindow);
  663.  
  664.         WITH anInspectWindow DO
  665.             BEGIN
  666.  
  667.             fClassListView := TClassListView(FindSubView('IVW1'));
  668.             fObjListView := TObjListView(FindSubView('IVW2'));
  669.             fObjectView := TObjectView(FindSubView('IVW3'));
  670.  
  671.             fClassListView.fInspectWindow := anInspectWindow;
  672.             fObjListView.fInspectWindow := anInspectWindow;
  673.             fObjectView.fInspectWindow := anInspectWindow;
  674.  
  675.             { Use GetMaxIntersectedDevice to Locate our window. }
  676.             IF GetMaxIntersectedDevice(screenRect) = NIL THEN;
  677.             WITH screenRect DO
  678.                 BEGIN
  679.                 Locate(right - fWMgrWindow^.portRect.right, top + fContRgnInset.v, kDontInvalidate);
  680.  
  681.                 {Adapt height of window to height of screen}
  682.                 IF bottom > 342 THEN
  683.                     Resize(fWMgrWindow^.portRect.right, Max(252, bottom - 192), kDontInvalidate);
  684.  
  685.                 END;
  686.             END;
  687.         END
  688.  
  689.     ELSE
  690.         BEGIN
  691.         New(anInspectWindow);
  692.         FailNIL(anInspectWindow);
  693.         anInspectWindow.IInspectWindow;
  694.         anInspectWindow.ForceOnScreen;
  695.         END;
  696.  
  697.     WITH anInspectWindow DO
  698.         BEGIN
  699.         staggerCount := fStaggerCount;
  700.         SimpleStagger( - kStdStaggerAmount, kStdStaggerAmount, staggerCount);
  701.         fStaggerCount := staggerCount;
  702.  
  703.         SetNumberOfClasses(fClassesByID.GetSize);
  704.  
  705. { Installs print handler if client app is using printing }
  706.         InstallIfPrintHandler(gPrintHandler, fObjectView);
  707.  
  708.         END;
  709.  
  710.     MakeWindow := anInspectWindow;
  711.     END;
  712.  
  713. {---------------------------------------------------------------------------}
  714.  
  715. PROCEDURE TInspector.AddObject(theObject: TObject);
  716.  
  717.     VAR
  718.         classId:            ObjClassID;
  719.         theObjectList:        TObjectList;
  720.  
  721.     PROCEDURE ResetObjListView(aWindow: TInspectWindow);
  722.  
  723.         VAR
  724.             objListView:        TObjListView;
  725.  
  726.         BEGIN
  727.         objListView := aWindow.fObjListView;
  728.         IF objListView.fObjectList = theObjectList THEN
  729.             objListView.InsertItem(objListView.fNumberOfItems + 1);
  730.         END;
  731.  
  732.     BEGIN
  733.  {Don't attempt to add TObjectList objects.  If we did, then we would
  734.   wind up in an infinite loop attempting to create TObjectLists.}
  735.     IF NOT Member(theObject, TObjectList) THEN
  736.         BEGIN
  737.         GetFocus(pSavedFocus);
  738.         gPrinting := False;
  739.         gDrawingPictScrap := False;
  740.         gDrawingPictScrapView := NIL;
  741.         classId := GetClassID(theObject);
  742.         theObjectList := GetObjectList(classId);
  743.         IF theObjectList = NIL THEN
  744.             theObjectList := AddObjectList(classId);
  745.         theObjectList.AddObject(theObject);
  746.         IF (fWindowList <> NIL) & (fWindowList.GetSize > 0) THEN
  747.             BEGIN
  748.             ForAllWindowsDo(ResetObjListView);
  749.             END;
  750.         SetFocus(pSavedFocus);
  751.         END;
  752.     END;
  753.  
  754. {---------------------------------------------------------------------------}
  755.  
  756. FUNCTION TInspector.AddObjectList(classId: ObjClassID): TObjectList;
  757.  
  758.     VAR
  759.         anObjectList:        TObjectList;
  760.         classListItemNo:    INTEGER;
  761.  
  762.     PROCEDURE ResetClassListView(aWindow: TInspectWindow);
  763.  
  764.         BEGIN
  765.         aWindow.InsertClass(classListItemNo);
  766.         END;
  767.  
  768.     BEGIN
  769.     New(anObjectList);
  770.     FailNIL(anObjectList);
  771.     anObjectList.IObjectList(classId);
  772.     fClassesByID.Insert(anObjectList);
  773.     fClassesByName.Insert(anObjectList);
  774.     classListItemNo := fClassesByName.GetSameItemNo(anObjectList);
  775.     ForAllWindowsDo(ResetClassListView);
  776.     AddObjectList := anObjectList;
  777.     END;
  778.  
  779. {---------------------------------------------------------------------------}
  780.  
  781. PROCEDURE TInspector.DoSetupMenus; OVERRIDE;
  782.  
  783.     BEGIN
  784.     INHERITED DoSetupMenus;
  785.  
  786.     Enable(cSaveAs, False);
  787.     Enable(cSaveCopy, False);
  788.     END;
  789.  
  790. {---------------------------------------------------------------------------}
  791.  
  792. FUNCTION TInspector.GetObjectList(classId: ObjClassID): TObjectList;
  793.  
  794.     FUNCTION TestClass(anObjectList: TObjectList): INTEGER;
  795.  
  796.         BEGIN
  797.         IF classId < anObjectList.fObjClassId THEN
  798.             TestClass := kItemGreaterThanCriteria
  799.         ELSE IF classId > anObjectList.fObjClassId THEN
  800.             TestClass := kItemLessThanCriteria
  801.         ELSE
  802.             TestClass := kItemEqualCriteria;
  803.         END;
  804.  
  805.     BEGIN
  806.     GetObjectList := TObjectList(fClassesByID.Search(TestClass));
  807.     END;
  808.  
  809. {---------------------------------------------------------------------------}
  810.  
  811. PROCEDURE TInspector.RemoveObject(theObject: TObject);
  812.  
  813.     VAR
  814.         theObjectList:        TObjectList;
  815.         index:                INTEGER;
  816.  
  817.     PROCEDURE CheckWindow(theInspectWindow: TInspectWindow);
  818.  
  819.         BEGIN
  820.         IF theInspectWindow.fObjectView.fObject = theObject THEN
  821.             theInspectWindow.fObjectView.InstallObject(NIL, 0);
  822.         IF theInspectWindow.fObjListView.fObjectList = theObjectList THEN
  823.             theInspectWindow.fObjListView.DeleteItem(index);
  824.         END;
  825.  
  826.     BEGIN
  827.     IF (fClassesByID <> NIL) & (NOT Member(theObject, TObjectList)) THEN
  828.         BEGIN
  829.         GetFocus(pSavedFocus);
  830.         gPrinting := False;
  831.         gDrawingPictScrap := False;
  832.         gDrawingPictScrapView := NIL;
  833.         theObjectList := GetObjectList(IntegerHandle(theObject)^^);
  834.         IF theObjectList <> NIL THEN
  835.             BEGIN
  836.             index := theObjectList.GetEqualItemNo(theObject);
  837.             theObjectList.RemoveObject(theObject);
  838.             IF (fWindowList <> NIL) & (fWindowList.GetSize > 0) THEN
  839.                 BEGIN
  840.                 ForAllWindowsDo(CheckWindow);
  841.                 END;
  842.             END;
  843.         SetFocus(pSavedFocus);
  844.         END;
  845.     END;
  846.  
  847. {---------------------------------------------------------------------------}
  848.  
  849. PROCEDURE TInspectWindow.IRes(itsDocument: TDocument;
  850.                               itsSuperView: TView;
  851.                               VAR itsParams: Ptr); OVERRIDE;
  852.  
  853.     BEGIN
  854.     fClassListView := NIL;
  855.     fObjListView := NIL;
  856.     fObjectView := NIL;
  857.  
  858.     INHERITED IRes(itsDocument, itsSuperView, itsParams);
  859.  
  860.     {$Push} {$H-}
  861.     SetPt(fResizeLimits.topLeft, 151, 142);
  862.     {$Pop}
  863.     END;
  864.  
  865. {---------------------------------------------------------------------------}
  866.  
  867. PROCEDURE TInspectWindow.IInspectWindow;
  868.  
  869.     VAR
  870.         aWMgrWindow:        WindowPtr;
  871.         canResize:            BOOLEAN;
  872.         canClose:            BOOLEAN;
  873.         fi:                 FailInfo;
  874.         aClassListView:     TClassListView;
  875.         anObjListView:        TObjListView;
  876.         anObjectView:        TObjectView;
  877.         aScroller:            TScroller;
  878.         itsLocation:        VPoint;
  879.         itsSize:            VPoint;
  880.         screenRect:         Rect;
  881.  
  882.     PROCEDURE HandleFailure(error: INTEGER;
  883.                             message: LONGINT);
  884.  
  885.         BEGIN
  886.         {the wmgrWindow is known to exist}
  887.   {Since aWindow didn't get created, the wmgrWindow won't be
  888.    freed unless we do it here.}
  889.  
  890.         aWMgrWindow := FreeIfWMgrWindow(aWMgrWindow, TRUE);
  891.  
  892.         END;
  893.  
  894.     BEGIN
  895.     fClassListView := NIL;
  896.     fObjListView := NIL;
  897.     fObjectView := NIL;
  898.  
  899.     aWMgrWindow := NIL;
  900.     aWMgrWindow := gApplication.GetRsrcWindow(NIL, kInspectorWindowType, canResize, canClose);
  901.     {GetRsrcWindow signals Failure}
  902.  
  903.     CatchFailures(fi, HandleFailure);
  904.     IWindow(pInspector, aWMgrWindow, canResize, canClose, TRUE);
  905.     {$Push} {$H-}
  906.     SetPt(fResizeLimits.topLeft, 151, 142);
  907.     {$Pop}
  908.  
  909.     fClosesDocument := False;
  910.     fFreeOnClosing := TRUE;
  911.  
  912.     SetVPt(itsLocation, 0, 0);
  913.     SetVPt(itsSize, 65, 12 * 6);
  914.     New(aClassListView);
  915.     FailNIL(aClassListView);
  916.     aClassListView.IClassListView(SELF, itsLocation, itsSize);
  917.     fClassListView := aClassListView;
  918.  
  919.     SetVPt(itsLocation, 81, 0);
  920.     SetVPt(itsSize, 200 - 81, 12 * 6);
  921.     New(anObjListView);
  922.     FailNIL(anObjListView);
  923.     anObjListView.IObjListView(SELF, itsLocation, itsSize);
  924.     fObjListView := anObjListView;
  925.  
  926.     SetVPt(itsLocation, 0, 12 * 6 + 1);
  927.     SetVPt(itsSize, 200, fWMgrWindow^.portRect.bottom - itsLocation.v);
  928.     New(anObjectView);
  929.     FailNIL(anObjectView);
  930.     anObjectView.IObjectView(SELF, itsLocation, itsSize);
  931.     fObjectView := anObjectView;
  932.  
  933.     SetTarget(anObjectView);                            { !!! }
  934.  
  935.     fSize := gZeroVPt;                                    { Make sure window gets resized }
  936.     WITH fWMgrWindow^.portRect DO
  937.         Resize(right - left, bottom - top, kDontInvalidate);
  938.  
  939.     { Use GetMaxIntersectedDevice to Locate our window. }
  940.     IF GetMaxIntersectedDevice(screenRect) = NIL THEN;
  941.     WITH screenRect DO
  942.         BEGIN
  943.         Locate(right - fWMgrWindow^.portRect.right, top + fContRgnInset.v, kDontInvalidate);
  944.  
  945.         {Adapt height of window to height of screen}
  946.         IF bottom > 342 THEN
  947.             Resize(fWMgrWindow^.portRect.right, Max(252, bottom - 192), kDontInvalidate);
  948.         END;
  949.  
  950.     Success(fi);
  951.     END;
  952.  
  953. {---------------------------------------------------------------------------}
  954.  
  955. PROCEDURE TInspectWindow.CloseByUser; OVERRIDE;
  956.  
  957.     BEGIN
  958.  {Overridden to prevent closing the Inspector document when the last
  959.   inspector window is closed.}
  960.     Close;
  961.     END;
  962.  
  963. {---------------------------------------------------------------------------}
  964.  
  965. PROCEDURE TInspectWindow.Draw(area: Rect); OVERRIDE;
  966.  
  967.     BEGIN
  968.     INHERITED Draw(area);
  969.  
  970.     {Draw horizontal line separating upper views from lower view}
  971.     PenNormal;
  972.     MoveTo(0, fObjectView.fSuperView.fLocation.v - 1);
  973.     Line(fSize.h, 0);
  974.     END;
  975.  
  976. {---------------------------------------------------------------------------}
  977.  
  978. PROCEDURE TInspectWindow.Fields(PROCEDURE DoToField(fieldName: Str255;
  979.                                                     fieldAddr: Ptr;
  980.                                                     fieldType: INTEGER)); OVERRIDE;
  981.  
  982.     BEGIN
  983.     DoToField('TInspectWindow', NIL, bClass);
  984.     DoToField('fClassListView', @fClassListView, bObject);
  985.     DoToField('fObjListView', @fObjListView, bObject);
  986.     DoToField('fObjectView', @fObjectView, bObject);
  987.     INHERITED Fields(DoToField);
  988.     END;
  989.  
  990. {---------------------------------------------------------------------------}
  991.  
  992. PROCEDURE TInspectWindow.Resize(width, height: VCoordinate;
  993.                                 invalidate: BOOLEAN); OVERRIDE;
  994.  
  995.     BEGIN
  996.     INHERITED Resize(width, height, invalidate);
  997.  
  998.  {Resize the upper-right and bottom view to match the window's
  999.   new size.}
  1000.     IF fClassListView <> NIL THEN
  1001.         BEGIN
  1002.         WITH fClassListView.fSuperView DO
  1003.             fClassListView.fSuperView.Resize(BSR(width, 1) - kSBarSizeMinus1, fSize.v, invalidate);
  1004.         END;
  1005.     IF fObjListView <> NIL THEN
  1006.         BEGIN
  1007.         fObjListView.fSuperView.Locate(BSR(width, 1) + 1, 0, invalidate);
  1008.         WITH fObjListView.fSuperView DO
  1009.             fObjListView.fSuperView.Resize(width - fLocation.h - kSBarSizeMinus1, fSize.v,
  1010.                                            invalidate);
  1011.         END;
  1012.     IF fObjectView <> NIL THEN
  1013.         BEGIN
  1014.         WITH fObjectView.fSuperView DO
  1015.             fObjectView.fSuperView.Resize(width - kSBarSizeMinus1, (height -
  1016.                                           fObjectView.fSuperView.fLocation.v) - kSBarSizeMinus1,
  1017.                                           invalidate);
  1018.         END;
  1019.     END;
  1020.  
  1021. {---------------------------------------------------------------------------}
  1022.  
  1023. PROCEDURE TInspectWindow.InsertClass(itemNo: INTEGER);
  1024.  
  1025.     BEGIN
  1026.     IF fClassListView <> NIL THEN
  1027.         fClassListView.InsertItem(itemNo);
  1028.     END;
  1029.  
  1030. {---------------------------------------------------------------------------}
  1031.  
  1032. PROCEDURE TInspectWindow.SetNumberOfClasses(noOfClasses: INTEGER);
  1033.  
  1034.     BEGIN
  1035.     IF fClassListView <> NIL THEN
  1036.         fClassListView.SetNumberOfItems(noOfClasses);
  1037.     END;
  1038.  
  1039. {---------------------------------------------------------------------------}
  1040.  
  1041. PROCEDURE TInspectWindow.SetTitleForDoc(newDocTitle: Str255); OVERRIDE;
  1042.  
  1043.     BEGIN
  1044.     SetTitle(ConcatNumber('Inspector ', pInspector.fWindowCount));
  1045.     END;
  1046.  
  1047. {---------------------------------------------------------------------------}
  1048.  
  1049. PROCEDURE TInspectWindow.SelectObject(theObject: TObject;
  1050.                                       theType: INTEGER);
  1051.  
  1052.  {This installs the given object as the selected object of the window,
  1053.   making sure that the class list and object list views are in sync.}
  1054.  
  1055.     VAR
  1056.         objectItemNumber, classItemNumber: INTEGER;
  1057.         classId:            ObjClassID;
  1058.         anObjectList:        TObjectList;
  1059.         anObject:            TObject;
  1060.  
  1061.     FUNCTION TestClass(anObjectList: TObjectList): BOOLEAN;
  1062.  
  1063.         BEGIN
  1064.         classItemNumber := classItemNumber + 1;
  1065.         TestClass := anObjectList.fObjClassId = classId;
  1066.         END;
  1067.  
  1068.     FUNCTION TestObject(anObject: TObject): BOOLEAN;
  1069.  
  1070.         BEGIN
  1071.         objectItemNumber := objectItemNumber + 1;
  1072.         TestObject := anObject = theObject;
  1073.         END;
  1074.  
  1075.     BEGIN
  1076.     IF NOT (ODD(LONGINT(theObject))) THEN                {* check for uninitialized object *}
  1077.         BEGIN
  1078.         IF theType = bObject THEN
  1079.             BEGIN
  1080.             {* get the new class *}
  1081.             classItemNumber := 0;
  1082.             classId := GetClassID(theObject);
  1083.             anObjectList := TObjectList(pInspector.fClassesByName.FirstThat(TestClass));
  1084.             IF anObjectList <> NIL THEN
  1085.                 BEGIN
  1086.                 objectItemNumber := 0;
  1087.                 anObject := anObjectList.FirstThat(TestObject);
  1088.                 IF anObject <> NIL THEN
  1089.                     BEGIN
  1090.                     { turn off the old class and select the new class }
  1091.                     fClassListView.ChangeSelection(classItemNumber, TRUE);
  1092.                     fClassListView.RevealItem(classItemNumber);
  1093.                     { turn off the old item and select the new item }
  1094.                     fObjListView.ChangeSelection(objectItemNumber, TRUE);
  1095.                     END;
  1096.                 END
  1097.                 {$IFC qDebugTheDebugger}
  1098.             ELSE
  1099.                 BEGIN
  1100.                 ProgramBreak('TInspectWindow.SelectObject: Unable to find class');
  1101.                 END
  1102.                 {$ENDC}
  1103.             ;
  1104.             END
  1105.  
  1106.         ELSE IF theType <> 0 THEN
  1107.             fObjectView.InstallObject(theObject, theType);
  1108.         END;
  1109.     END;
  1110.  
  1111. { Based on work by Kurt Shmucker Copyright 1986 by Productivity Products International, Inc.
  1112.     Used by permission. }
  1113.  
  1114. {---------------------------------------------------------------------------}
  1115.  
  1116. PROCEDURE TListView.IRes(itsDocument: TDocument;
  1117.                          itsSuperView: TView;
  1118.                          VAR itsParams: Ptr); OVERRIDE;
  1119.  
  1120.     BEGIN
  1121.     INHERITED IRes(itsDocument, itsSuperView, itsParams);
  1122.  
  1123.     fCurrentSelection := 0;
  1124.     fNumberOfItems := 0;
  1125.     SetStyle(pInspectorStyle);
  1126.     END;
  1127.  
  1128. {--------------------------------------------------------------------------------------------------}
  1129.  
  1130. PROCEDURE TListView.IListView(itsDocument: TDocument;
  1131.                               itsSuperView: TView;
  1132.                               itsLocation: VPoint;
  1133.                               itsSize: VPoint;
  1134.                               itsTextStyle: TextStyle;
  1135.                               itsNumberOfItems: INTEGER;
  1136.                               itsHSizeDet: SizeDeterminer);
  1137.  
  1138.     BEGIN
  1139.     IView(itsDocument, itsSuperView, itsLocation, itsSize, itsHSizeDet, sizeVariable);
  1140.     fCurrentSelection := 0;                             {No item is initially selected}
  1141.     fNumberOfItems := itsNumberOfItems;
  1142.     SetStyle(itsTextStyle);
  1143.     END;
  1144.  
  1145. {--------------------------------------------------------------------------------------------------}
  1146.  
  1147. PROCEDURE TListView.CalcMinSize(VAR minSize: VPoint); OVERRIDE;
  1148.  
  1149.     BEGIN
  1150.     INHERITED CalcMinSize(minSize);
  1151.     { Set the amount of room needed for that many items }
  1152.     minSize.v := IntMultiply(fNumberOfItems, fItemHeight);
  1153.  
  1154.     IF fNumberOfItems <> 0 THEN
  1155.         minSize.h := Max(600, fSuperView.fSize.h)
  1156.     ELSE
  1157.         minSize.h := 0;
  1158.     END;
  1159.  
  1160. {--------------------------------------------------------------------------------------------------}
  1161.  
  1162. PROCEDURE TListView.ChangeSelection(index: INTEGER;
  1163.                                     highlight: BOOLEAN);
  1164.  
  1165.     BEGIN
  1166.     IF highlight & Focus & IsVisible THEN
  1167.         BEGIN
  1168.         DoHighlightSelection(fHLDesired, hlOff);
  1169.         fCurrentSelection := index;
  1170.         DoHighlightSelection(hlOff, fHLDesired);
  1171.         END
  1172.     ELSE
  1173.         fCurrentSelection := index;
  1174.     SelectItem(index);
  1175.     END;
  1176.  
  1177. {--------------------------------------------------------------------------------------------------}
  1178.  
  1179. PROCEDURE TListView.DeleteItem(itemNo: INTEGER);
  1180.  
  1181.     VAR
  1182.         topRect, bottomRect: VRect;
  1183.  
  1184.     BEGIN
  1185.     IF fCurrentSelection > 0 THEN
  1186.         IF itemNo < fCurrentSelection THEN
  1187.             fCurrentSelection := fCurrentSelection - 1
  1188.         ELSE IF itemNo = fCurrentSelection THEN
  1189.             fCurrentSelection := 0;
  1190.  
  1191.     fNumberOfItems := fNumberOfItems - 1;
  1192.     AdjustSize;
  1193.  
  1194.     { Invalidate from the deleted item to the end }
  1195.     ItemToVRect(itemNo, topRect);
  1196.     ItemToVRect(fNumberOfItems, bottomRect);
  1197.     topRect.bottom := bottomRect.bottom;
  1198.     InvalidVRect(topRect);
  1199.     END;
  1200.  
  1201. {--------------------------------------------------------------------------------------------------}
  1202.  
  1203. { Dim highlighting of text by gray XORing is not very readable, so dim highlight a text string
  1204. by framing it with a gray rectangle.  (Standard highlighting when the window displaying
  1205. the view is active is still to invert - black XORing.)    The state transition diagram is:
  1206.  
  1207.                                               hlTo
  1208.  
  1209.                       |     OFF      |           DIM          |       ON
  1210.            -----------|--------------|--------------------|--------------------
  1211.                OFF      |     (NA)     |          Frame       |      Invert
  1212.            -----------|--------------|--------------------|--------------------
  1213. hlFrom           DIM      |     Frame     |          (NA)          |  Frame and Invert
  1214.            -----------|--------------|--------------------|--------------------
  1215.                ON      |    Invert     |    Invert and Frame  |       (NA)
  1216.            -----------|--------------|-----------------------------------------
  1217.  
  1218. Since this matrix is (almost) symmetric, we can add together the hlFrom and hlTo parameters
  1219. and take one action for each of the three possible sums.  }
  1220.  
  1221. PROCEDURE TListView.DoHighlightSelection(fromHL, toHL: HLState); OVERRIDE;
  1222.  
  1223.     VAR
  1224.         itemVRect:            VRect;
  1225.         r:                    Rect;
  1226.  
  1227.     BEGIN
  1228.     IF (fCurrentSelection > 0) THEN
  1229.         BEGIN
  1230.         { Make r be the rectangle to invert }
  1231.         ItemToVRect(fCurrentSelection, itemVRect);
  1232.         ViewToQDRect(itemVRect, r);
  1233.  
  1234.         { Set the pen pattern and mode properly }
  1235.         PenPat(black);
  1236.         PenMode(patXor);
  1237.  
  1238.         IF RectIsVisible(r) THEN                        { only do highlighting if part of the
  1239.                                                          rectangle is visible }
  1240.             BEGIN
  1241.             CASE (fromHL + toHL) OF
  1242.                 hlOffDim:
  1243.                     BEGIN
  1244.                     UseSelectionColor;
  1245.                     FrameRect(r);
  1246.                     END;
  1247.                 hlOffOn:
  1248.                     BEGIN
  1249.                     UseSelectionColor;
  1250.                     InvertRect(r);
  1251.                     END;
  1252.                 hlDimOn:
  1253.                     IF fromHL = hlDim THEN
  1254.                         BEGIN
  1255.                         UseSelectionColor;
  1256.                         FrameRect(r);
  1257.                         UseSelectionColor;
  1258.                         InvertRect(r);
  1259.                         END
  1260.                     ELSE
  1261.                         BEGIN
  1262.                         UseSelectionColor;
  1263.                         InvertRect(r);
  1264.                         UseSelectionColor;
  1265.                         FrameRect(r);
  1266.                         END;
  1267.             END
  1268.             END
  1269.         END
  1270.     END;
  1271.  
  1272. {--------------------------------------------------------------------------------------------------}
  1273.  
  1274. FUNCTION TListView.DoMouseCommand(VAR theMouse: Point;
  1275.                                   VAR info: EventInfo;
  1276.                                   VAR hysteresis: Point): TCommand; OVERRIDE;
  1277.  
  1278.     VAR
  1279.         index:                INTEGER;
  1280.         theVMouse:            VPoint;
  1281.  
  1282.     BEGIN
  1283.     QDToViewPt(theMouse, theVMouse);
  1284.     index := VPointToItem(theVMouse);
  1285.     IF (index > 0) & (index <= fNumberOfItems) THEN
  1286.         ChangeSelection(index, TRUE);
  1287.     DoMouseCommand := NIL;
  1288.     END;
  1289.  
  1290. {--------------------------------------------------------------------------------------------------}
  1291.  
  1292. PROCEDURE TListView.Draw(area: Rect); OVERRIDE;
  1293.  
  1294.     VAR
  1295.         i, firstItem, lastItem: INTEGER;
  1296.         viewArea:            VRect;
  1297.         baseVPoint:         VPoint;
  1298.         basePoint:            Point;
  1299.  
  1300.     BEGIN
  1301.     SetPen;
  1302.     QDToViewRect(area, viewArea);
  1303.     WITH viewArea DO
  1304.         BEGIN
  1305.         {adjust for QuickDraw geometry}
  1306.         bottom := bottom - 1;
  1307.         right := right - 1;
  1308.  
  1309.         firstItem := top DIV fItemHeight + 1;
  1310.         lastItem := Min(fNumberOfItems, bottom DIV fItemHeight + 1);
  1311.         END;
  1312.  
  1313.     SetVPt(baseVPoint, 4, IntMultiply(firstItem - 1, fItemHeight) + fLineAscent);
  1314.     basePoint := ViewToQDPt(baseVPoint);
  1315.     FOR i := firstItem TO lastItem DO
  1316.         BEGIN
  1317.         DrawItem(i, basePoint);
  1318.         basePoint.v := basePoint.v + fItemHeight;
  1319.         END;
  1320.  
  1321.     INHERITED Draw(area);
  1322.     END;
  1323.  
  1324. {--------------------------------------------------------------------------------------------------}
  1325.  
  1326. PROCEDURE TListView.DrawItem(itemNumber: INTEGER;
  1327.                              basePoint: Point);
  1328.  
  1329.     BEGIN
  1330.     {Should always be overridden.}
  1331.     END;
  1332.  
  1333. {--------------------------------------------------------------------------------------------------}
  1334.  
  1335. PROCEDURE TListView.Fields(PROCEDURE DoToField(fieldName: Str255;
  1336.                                                fieldAddr: Ptr;
  1337.                                                fieldType: INTEGER)); OVERRIDE;
  1338.  
  1339.     BEGIN
  1340.     DoToField('TListView', NIL, bClass);
  1341.     DoToField('fCurrentSelection', @fCurrentSelection, bInteger);
  1342.     DoToField('fNumberOfItems', @fNumberOfItems, bInteger);
  1343.     {$Push} {$H-}
  1344.     TextStyleFields('fTextStyle', fTextStyle, DoToField);
  1345.     {$Pop}
  1346.     DoToField('fItemHeight', @fItemHeight, bInteger);
  1347.     DoToField('fLineAscent', @fLineAscent, bInteger);
  1348.     INHERITED Fields(DoToField);
  1349.     END;
  1350.  
  1351. {--------------------------------------------------------------------------------------------------}
  1352.  
  1353. PROCEDURE TListView.InsertItem(itemNo: INTEGER);
  1354.  
  1355.     VAR
  1356.         topRect, bottomRect: VRect;
  1357.  
  1358.     BEGIN
  1359.     IF (fCurrentSelection > 0) & (itemNo <= fCurrentSelection) THEN
  1360.         fCurrentSelection := fCurrentSelection + 1;
  1361.  
  1362.     fNumberOfItems := fNumberOfItems + 1;
  1363.     AdjustSize;
  1364.  
  1365.     { Invalidate from the inserted item to the end }
  1366.     ItemToVRect(itemNo, topRect);
  1367.     ItemToVRect(fNumberOfItems, bottomRect);
  1368.     topRect.bottom := bottomRect.bottom;
  1369.     InvalidVRect(topRect);
  1370.     END;
  1371.  
  1372. {--------------------------------------------------------------------------------------------------}
  1373.  
  1374. PROCEDURE TListView.ItemToVRect(index: INTEGER;
  1375.                                 VAR itemRect: VRect);
  1376.  
  1377.     BEGIN
  1378.     GetExtent(itemRect);
  1379.     itemRect.top := IntMultiply(index - 1, fItemHeight); { Subtract 1 to get the TOP line }
  1380.     itemRect.bottom := itemRect.top + fItemHeight;
  1381.     END;
  1382.  
  1383. {--------------------------------------------------------------------------------------------------}
  1384.  
  1385. PROCEDURE TListView.RevealItem(itemNumber: INTEGER);
  1386.  
  1387.     VAR
  1388.         howMuch:            Point;
  1389.         rectToReveal:        VRect;
  1390.  
  1391.     BEGIN
  1392.     SetPt(howMuch, 0, fItemHeight);
  1393.     ItemToVRect(itemNumber, rectToReveal);
  1394.     RevealRect(rectToReveal, howMuch, kRedraw);
  1395.     END;
  1396.  
  1397. {--------------------------------------------------------------------------------------------------}
  1398.  
  1399. PROCEDURE TListView.SelectItem(itemNumber: INTEGER);
  1400.  
  1401.     BEGIN
  1402.     {Can be overridden to do something when an item is selected.}
  1403.     END;
  1404.  
  1405. {--------------------------------------------------------------------------------------------------}
  1406.  
  1407. PROCEDURE TListView.SetNumberOfItems(numberOfItems: INTEGER);
  1408.  
  1409.     BEGIN
  1410.     IF numberOfItems <> fNumberOfItems THEN
  1411.         BEGIN
  1412.         fNumberOfItems := numberOfItems;
  1413.         AdjustSize;
  1414.         END;
  1415.     ForceRedraw;
  1416.     END;
  1417.  
  1418. {--------------------------------------------------------------------------------------------------}
  1419.  
  1420. PROCEDURE TListView.SetStyle(itsTextStyle: TextStyle);
  1421.  
  1422.     VAR
  1423.         aPort:                GrafPort;
  1424.         savedPort:            GrafPtr;
  1425.         theFontInfo:        FontInfo;
  1426.  
  1427.     BEGIN
  1428.     fTextStyle := itsTextStyle;
  1429.  
  1430.     {Need a temporary port to set up the font, so we can get the font info}
  1431.     GetPort(savedPort);
  1432.     OpenPort(@aPort);
  1433.     SetPen;
  1434.     GetFontInfo(theFontInfo);
  1435.     WITH theFontInfo DO
  1436.         BEGIN
  1437.         fItemHeight := ascent + descent + leading;
  1438.         fLineAscent := ascent + (leading DIV 2) - 1;
  1439.         END;
  1440.     SetPort(savedPort);
  1441.     ClosePort(@aPort);
  1442.     AdjustSize;
  1443.     END                                                 {TListView.SetFont} ;
  1444.  
  1445. {--------------------------------------------------------------------------------------------------}
  1446.  
  1447. PROCEDURE TListView.SetPen;
  1448.  
  1449.     VAR
  1450.         itsTextStyle:        TextStyle;
  1451.  
  1452.     BEGIN
  1453.     PenNormal;
  1454.     itsTextStyle := fTextStyle;
  1455.     SetPortTextStyle(itsTextStyle);
  1456.     END;
  1457.  
  1458. {--------------------------------------------------------------------------------------------------}
  1459.  
  1460. FUNCTION TListView.VPointToItem(thePoint: VPoint): INTEGER;
  1461.  
  1462.     BEGIN
  1463.     VPointToItem := (thePoint.v DIV fItemHeight) + 1;
  1464.     END;
  1465.  
  1466. {---------------------------------------------------------------------------}
  1467.  
  1468. PROCEDURE TClassListView.IRes(itsDocument: TDocument;
  1469.                               itsSuperView: TView;
  1470.                               VAR itsParams: Ptr); OVERRIDE;
  1471.  
  1472.     BEGIN
  1473.     INHERITED IRes(itsDocument, itsSuperView, itsParams);
  1474.  
  1475.     GetScroller(TRUE).SetScrollParameters(0, fItemHeight, False, TRUE);
  1476.     END;
  1477.  
  1478. {---------------------------------------------------------------------------}
  1479.  
  1480. PROCEDURE TClassListView.IClassListView(itsWindow: TInspectWindow;
  1481.                                         itsLocation: VPoint;
  1482.                                         itsSize: VPoint);
  1483.  
  1484.     VAR
  1485.         aScroller:            TScroller;
  1486.  
  1487.     BEGIN
  1488.     New(aScroller);
  1489.     FailNIL(aScroller);
  1490.     aScroller.IScroller(itsWindow, itsLocation, itsSize, sizeFixed, sizeFixed, 0, 1000, False,
  1491.                         TRUE);
  1492.  
  1493.     itsSize.v := 0;                                     { start off with no items }
  1494.     IListView(pInspector, aScroller, gZeroVPt, itsSize, pInspectorStyle, 0, sizeFixed);
  1495.  
  1496.     aScroller.SetScrollParameters(0, fItemHeight, False, TRUE);
  1497.  
  1498.     fInspectWindow := itsWindow;
  1499.     END;
  1500.  
  1501. {---------------------------------------------------------------------------}
  1502.  
  1503. PROCEDURE TClassListView.DrawItem(itemNumber: INTEGER;
  1504.                                   basePoint: Point); OVERRIDE;
  1505.  
  1506.     VAR
  1507.         className:            MAName;
  1508.         aStringPtr:         StringPtr;
  1509.  
  1510.     BEGIN
  1511.     GetClassNameFromID(TObjectList(pInspector.fClassesByName.At(itemNumber)).fObjClassId,
  1512.                        className);
  1513.     MoveTo(basePoint.h, basePoint.v);
  1514.     aStringPtr := StringPtr(@className);
  1515.     DrawString(aStringPtr^);
  1516.     END;
  1517.  
  1518. {---------------------------------------------------------------------------}
  1519.  
  1520. PROCEDURE TClassListView.SelectItem(itemNumber: INTEGER); OVERRIDE;
  1521.  
  1522.     VAR
  1523.         theObjectList:        TObjectList;
  1524.  
  1525.     BEGIN
  1526.     IF itemNumber > 0 THEN
  1527.         BEGIN
  1528.         theObjectList := TObjectList(pInspector.fClassesByName.At(itemNumber));
  1529.         IF (fInspectWindow.fObjListView <> NIL) THEN
  1530.             fInspectWindow.fObjListView.InstallObjectList(theObjectList)
  1531.         ELSE
  1532.             fInspectWindow.fObjListView.ChangeSelection(0, TRUE);
  1533.         END;
  1534.  
  1535.     INHERITED SelectItem(itemNumber);
  1536.     END;
  1537.  
  1538. {---------------------------------------------------------------------------}
  1539.  
  1540. PROCEDURE TClassListView.Fields(PROCEDURE DoToField(fieldName: Str255;
  1541.                                                     fieldAddr: Ptr;
  1542.                                                     fieldType: INTEGER)); OVERRIDE;
  1543.  
  1544.     BEGIN
  1545.     DoToField('TClassListView', NIL, bClass);
  1546.     DoToField('fInspectWindow', @fInspectWindow, bObject);
  1547.     INHERITED Fields(DoToField);
  1548.     END;
  1549.  
  1550. {---------------------------------------------------------------------------}
  1551.  
  1552. PROCEDURE TObjListView.IRes(itsDocument: TDocument;
  1553.                             itsSuperView: TView;
  1554.                             VAR itsParams: Ptr); OVERRIDE;
  1555.  
  1556.     BEGIN
  1557.     INHERITED IRes(itsDocument, itsSuperView, itsParams);
  1558.  
  1559.     GetScroller(TRUE).SetScrollParameters(0, fItemHeight, FALSE, TRUE);
  1560.     fObjectList := NIL;
  1561.     END;
  1562.  
  1563. {---------------------------------------------------------------------------}
  1564.  
  1565. PROCEDURE TObjListView.IObjListView(itsWindow: TInspectWindow;
  1566.                                     itsLocation: VPoint;
  1567.                                     itsSize: VPoint);
  1568.  
  1569.     VAR
  1570.         aScroller:            TScroller;
  1571.  
  1572.     BEGIN
  1573.     New(aScroller);
  1574.     FailNIL(aScroller);
  1575.     aScroller.IScroller(itsWindow, itsLocation, itsSize, sizeRelSuperView, sizeFixed, 0, 1000,
  1576.                         kWantHScrollBar, kWantVScrollBar);
  1577.     itsSize.v := 0;                                     { Start off with no items }
  1578.     IListView(pInspector, aScroller, gZeroVPt, itsSize, pInspectorStyle, 0, sizeRelSuperView);
  1579.     aScroller.SetScrollParameters(0, fItemHeight, FALSE, TRUE);
  1580.     fInspectWindow := itsWindow;
  1581.     fObjectList := NIL;
  1582.     END;
  1583.  
  1584. {---------------------------------------------------------------------------}
  1585.  
  1586. PROCEDURE TObjListView.DrawItem(itemNumber: INTEGER;
  1587.                                 basePoint: Point); OVERRIDE;
  1588.  
  1589.     VAR
  1590.         s1:                 Str255;
  1591.         aString:            Str255;
  1592.         theObject:            TObject;
  1593.  
  1594.     BEGIN
  1595.     theObject := fObjectList.At(itemNumber);
  1596.     PointerToHex(ORD4(theObject), s1, 6);
  1597.     aString := '';
  1598.     theObject.GetInspectorName(aString);
  1599.     aString := CONCAT(s1, ': ', aString);
  1600.     MoveTo(basePoint.h, basePoint.v);
  1601.     DrawString(aString);
  1602.     END;
  1603.  
  1604. {---------------------------------------------------------------------------}
  1605.  
  1606. PROCEDURE TObjListView.SelectItem(itemNumber: INTEGER); OVERRIDE;
  1607.  
  1608.     BEGIN
  1609.  {Assume that we've gotten here only if the field is one that can
  1610.   be selected.}
  1611.     IF itemNumber > 0 THEN
  1612.         fInspectWindow.fObjectView.InstallObject(fObjectList.At(itemNumber), bObject);
  1613.  
  1614.     INHERITED SelectItem(itemNumber);
  1615.     END;
  1616.  
  1617. {---------------------------------------------------------------------------}
  1618.  
  1619. PROCEDURE TObjListView.Fields(PROCEDURE DoToField(fieldName: Str255;
  1620.                                                   fieldAddr: Ptr;
  1621.                                                   fieldType: INTEGER)); OVERRIDE;
  1622.  
  1623.     BEGIN
  1624.     DoToField('TObjListView', NIL, bClass);
  1625.     DoToField('fInspectWindow', @fInspectWindow, bObject);
  1626.     DoToField('fObjectList', @fObjectList, bObject);
  1627.     INHERITED Fields(DoToField);
  1628.     END;
  1629.  
  1630. {---------------------------------------------------------------------------}
  1631.  
  1632. PROCEDURE TObjListView.InstallObjectList(theObjectList: TObjectList);
  1633.  
  1634.     BEGIN
  1635.     ChangeSelection(0, TRUE);
  1636.     IF fObjectList <> theObjectList THEN
  1637.         BEGIN
  1638.         fObjectList := theObjectList;
  1639.         SetNumberOfItems(theObjectList.GetSize);
  1640.         RevealTop(kDontRedraw);
  1641.         ForceRedraw;
  1642.         END;
  1643.     END;
  1644.  
  1645. {---------------------------------------------------------------------------}
  1646.  
  1647. PROCEDURE TObjectView.IRes(itsDocument: TDocument;
  1648.                            itsSuperView: TView;
  1649.                            VAR itsParams: Ptr); OVERRIDE;
  1650.  
  1651.     BEGIN
  1652.     INHERITED IRes(itsDocument, itsSuperView, itsParams);
  1653.  
  1654.     GetScroller(TRUE).SetScrollParameters(kSBarSize, fItemHeight, TRUE, TRUE);
  1655.     fObject := NIL;
  1656.     END;
  1657.  
  1658. {---------------------------------------------------------------------------}
  1659.  
  1660. PROCEDURE TObjectView.IObjectView(itsWindow: TInspectWindow;
  1661.                                   itsLocation: VPoint;
  1662.                                   itsSize: VPoint);
  1663.  
  1664.     VAR
  1665.         aScroller:            TScroller;
  1666.  
  1667.     BEGIN
  1668.     New(aScroller);
  1669.     FailNIL(aScroller);
  1670.     aScroller.IScroller(itsWindow, itsLocation, itsSize, sizeRelSuperView, sizeRelSuperView, 0,
  1671.                         1000, TRUE, TRUE);
  1672.     aScroller.fSBarOffsets.bottom := - kSBarSizeMinus1;
  1673.  
  1674.     itsSize.v := 0;                                     { start off with no items }
  1675.     IListView(pInspector, aScroller, gZeroVPt, itsSize, pInspectorStyle, 0, sizeVariable);
  1676.     aScroller.SetScrollParameters(kSBarSize, fItemHeight, TRUE, TRUE);
  1677.     fInspectWindow := itsWindow;
  1678.     fObject := NIL;
  1679.     END;
  1680.  
  1681. {---------------------------------------------------------------------------}
  1682.  
  1683. PROCEDURE TObjectView.InspectControlHandle(PROCEDURE
  1684.                                            InspectField(fieldName: StringPtr;
  1685.                                                         fieldAddr: Ptr;
  1686.                                                         fieldType: INTEGER));
  1687.  
  1688.     TYPE
  1689.  {This is an alias for the Control Manager ControlRecord.  The only
  1690.   difference is that this is an unpacked record and contrlVis and
  1691.   contrlHilite are combined in the contrlVisandHilite field.
  1692.   We must have an unpacked record to pass addresses of its fields.}
  1693.         UControlHandle        = ^UControlPtr;
  1694.         UControlPtr         = ^UnpackedControl;
  1695.         UnpackedControl     = RECORD
  1696.             nextControl:        ControlHandle;
  1697.             contrlOwner:        WindowPtr;
  1698.             contrlRect:         Rect;
  1699.             contrlVisandHilite: INTEGER;
  1700.             contrlValue:        INTEGER;
  1701.             contrlMin:            INTEGER;
  1702.             contrlMax:            INTEGER;
  1703.             contrlDefProc:        Handle;
  1704.             contrlData:         Handle;
  1705.             contrlAction:        ProcPtr;
  1706.             contrlrfCon:        LONGINT;
  1707.             contrlTitle:        Str255;
  1708.             END;
  1709.  
  1710.     VAR
  1711.         theControl:         UControlHandle;
  1712.         wasLocked:            BOOLEAN;
  1713.  
  1714.     BEGIN
  1715.     wasLocked := IsHandleLocked(Handle(theControl));
  1716.     LockHandleHigh(Handle(theControl));
  1717.     
  1718.     theControl := UControlHandle(fObject);
  1719.     WITH theControl^^ DO
  1720.         BEGIN
  1721.         InspectField(AtStr('nextControl'), @nextControl, bControlHandle);
  1722.         InspectField(AtStr('contrlOwner'), @contrlOwner, bWindowPtr);
  1723.         InspectField(AtStr('contrlRect'), @contrlRect, bRect);
  1724.         InspectField(AtStr('contrlVis'), @contrlVisandHilite, bHighByte);
  1725.         InspectField(AtStr('contrlHilite'), @contrlVisandHilite, bLowByte);
  1726.         InspectField(AtStr('contrlValue'), @contrlValue, bInteger);
  1727.         InspectField(AtStr('contrlMin'), @contrlMin, bInteger);
  1728.         InspectField(AtStr('contrlMax'), @contrlMax, bInteger);
  1729.         InspectField(AtStr('contrlDefProc'), @contrlDefProc, bHandle);
  1730.         InspectField(AtStr('contrlData'), @contrlData, bHandle);
  1731.         InspectField(AtStr('contrlrfCon'), @contrlrfCon, bHexLongInt);
  1732.         InspectField(AtStr('contrlTitle'), @contrlTitle, bString);
  1733.         END;
  1734.     
  1735.     IF NOT wasLocked THEN
  1736.         HUnlock(Handle(theControl));
  1737.     END;
  1738.  
  1739. {---------------------------------------------------------------------------}
  1740.  
  1741. PROCEDURE TObjectView.InspectGrafPtr(PROCEDURE InspectField(fieldName: StringPtr;
  1742.                                                             fieldAddr: Ptr;
  1743.                                                             fieldType: INTEGER));
  1744.  
  1745.     VAR
  1746.         thePort:            GrafPtr;
  1747.         theCPort:            CGrafPtr;
  1748.  
  1749.     BEGIN
  1750.     thePort := GrafPtr(fObject);
  1751.     theCPort := CGrafPtr(fObject);
  1752.     IF (qNeedsColorQD | gConfiguration.hasColorQD) & (BAND(theCPort^.portVersion, $C000) =
  1753.        $0000C000) THEN                                   { 2 hi bits. IM V pp. 49-50 }
  1754.         WITH theCPort^ DO
  1755.             BEGIN
  1756.             InspectField(AtStr('device'), @device, bInteger);
  1757.             InspectField(AtStr('portPixMap'), @portPixMap, bHandle);
  1758.             InspectField(AtStr('portVersion'), @portVersion, bHexInteger);
  1759.             InspectField(AtStr('grafVars'), @grafVars, bHandle);
  1760.             InspectField(AtStr('chExtra'), @chExtra, bInteger);
  1761.             InspectField(AtStr('pnLocHFrac'), @pnLocHFrac, bHexInteger);
  1762.             InspectField(AtStr('portRect'), @portRect, bRect);
  1763.             InspectField(AtStr('visRgn'), @visRgn, bRgnHandle);
  1764.             InspectField(AtStr('clipRgn'), @clipRgn, bRgnHandle);
  1765.             InspectField(AtStr('bkPixPat'), @bkPixPat, bHandle);
  1766.             InspectField(AtStr('rgbFgColor'), @rgbFgColor, bRGBColor);
  1767.             InspectField(AtStr('rgbBkColor'), @rgbBkColor, bRGBColor);
  1768.             InspectField(AtStr('pnLoc'), @pnLoc, bPoint);
  1769.             InspectField(AtStr('pnSize'), @pnSize, bPoint);
  1770.             InspectField(AtStr('pnMode'), @pnMode, bInteger);
  1771.             InspectField(AtStr('pnPixPat'), @pnPixPat, bHandle);
  1772.             InspectField(AtStr('fillPixPat'), @fillPixPat, bHandle);
  1773.             END
  1774.     ELSE
  1775.         WITH thePort^ DO
  1776.             BEGIN
  1777.             InspectField(AtStr('device'), @device, bInteger);
  1778.             InspectField(AtStr('portBits.baseAddr'), @portBits.baseAddr, bPointer);
  1779.             InspectField(AtStr('portBits.rowBytes'), @portBits.rowBytes, bInteger);
  1780.             InspectField(AtStr('portBits.bounds'), @portBits.bounds, bRect);
  1781.             InspectField(AtStr('portRect'), @portRect, bRect);
  1782.             InspectField(AtStr('visRgn'), @visRgn, bRgnHandle);
  1783.             InspectField(AtStr('clipRgn'), @clipRgn, bRgnHandle);
  1784.             InspectField(AtStr('bkPat'), @bkPat, bPattern);
  1785.             InspectField(AtStr('fillPat'), @fillPat, bPattern);
  1786.             InspectField(AtStr('pnLoc'), @pnLoc, bPoint);
  1787.             InspectField(AtStr('pnSize'), @pnSize, bPoint);
  1788.             InspectField(AtStr('pnMode'), @pnMode, bInteger);
  1789.             InspectField(AtStr('pnPat'), @pnPat, bPattern);
  1790.             END;
  1791.     {The rest of the fields are common to both GrafPorts and CGrafPorts}
  1792.     WITH thePort^ DO
  1793.         BEGIN
  1794.         InspectField(AtStr('pnVis'), @pnVis, bInteger);
  1795.         InspectField(AtStr('txFont'), @txFont, bInteger);
  1796.         InspectField(AtStr('txFace'), @txFace, bHexInteger);
  1797.         InspectField(AtStr('txMode'), @txMode, bInteger);
  1798.         InspectField(AtStr('txSize'), @txSize, bInteger);
  1799.         InspectField(AtStr('spExtra'), @spExtra, bFixed);
  1800.         InspectField(AtStr('fgColor'), @fgColor, bLongInt);
  1801.         InspectField(AtStr('bkColor'), @bkColor, bLongInt);
  1802.         InspectField(AtStr('colrBit'), @colrBit, bInteger);
  1803.         InspectField(AtStr('patStretch'), @patStretch, bInteger);
  1804.         InspectField(AtStr('picSave'), @picSave, bHandle);
  1805.         InspectField(AtStr('rgnSave'), @rgnSave, bHandle);
  1806.         InspectField(AtStr('polySave'), @polySave, bHandle);
  1807.         InspectField(AtStr('grafProcs'), @grafProcs, bPointer);
  1808.         END;
  1809.     END;
  1810.  
  1811. {---------------------------------------------------------------------------}
  1812.  
  1813. PROCEDURE TObjectView.InspectRgnHandle(PROCEDURE InspectField(fieldName: StringPtr;
  1814.                                                               fieldAddr: Ptr;
  1815.                                                               fieldType: INTEGER));
  1816.  
  1817.     VAR
  1818.         theRgn:             RgnHandle;
  1819.         wasLocked:            BOOLEAN;
  1820.  
  1821.     BEGIN
  1822.     wasLocked := IsHandleLocked(Handle(theRgn));
  1823.     LockHandleHigh(Handle(theRgn));
  1824.  
  1825.     theRgn := RgnHandle(fObject);
  1826.     WITH theRgn^^ DO
  1827.         BEGIN
  1828.         InspectField(AtStr('rgnSize'), @rgnSize, bInteger);
  1829.         InspectField(AtStr('rgnBBox'), @rgnBBox, bRect);
  1830.         END;
  1831.     
  1832.     IF NOT wasLocked THEN
  1833.         HUnlock(Handle(theRgn));
  1834.     END;
  1835.  
  1836. {---------------------------------------------------------------------------}
  1837.  
  1838. PROCEDURE TObjectView.InspectHandle(PROCEDURE InspectField(fieldName: StringPtr;
  1839.                                                            fieldAddr: Ptr;
  1840.                                                            fieldType: INTEGER));
  1841.  
  1842.     VAR
  1843.         theHandle:            Handle;
  1844.  
  1845.     PROCEDURE ShowMemory(startAddress, numBytes: LONGINT);
  1846.  
  1847.         VAR
  1848.             i:                    INTEGER;
  1849.             addr, lineAddr:     LONGINT;
  1850.             numeric:            STRING[40];
  1851.             ascii:                STRING[16];
  1852.             numPos:             INTEGER;
  1853.             ascPos:             INTEGER;
  1854.             decNumber:            LONGINT;
  1855.             chCode:             INTEGER;
  1856.             j:                    INTEGER;
  1857.  
  1858. {--------------------------------------------------------------------------------------------------}
  1859.  
  1860.         PROCEDURE BlankLine;
  1861.  
  1862.             CONST
  1863.                 k8Spaces            = '        ';
  1864.  
  1865.             BEGIN
  1866.             ascii := CONCAT(k8Spaces, k8Spaces);
  1867.             numeric := CONCAT(ascii, ascii, k8Spaces);
  1868.             numPos := 0;
  1869.             ascPos := 0;
  1870.             END;
  1871.  
  1872. {--------------------------------------------------------------------------------------------------}
  1873.  
  1874.         PROCEDURE PrintLine;
  1875.  
  1876.             VAR
  1877.                 aStr:                Str255;
  1878.                 tempString:         String8;
  1879.  
  1880.             BEGIN
  1881.             LIntToHex(lineAddr, tempString, 8);
  1882.             aStr := CONCAT('$', tempString, ': ', numeric, '  ', ascii);
  1883.             InspectField(AtStr(''), @aStr, bInternalString);
  1884.  
  1885.             END;
  1886.  
  1887.         BEGIN
  1888.         IF ODD(startAddress) THEN
  1889.             InspectField(AtStr('Odd Address'), NIL, bTitle)
  1890.         ELSE IF numBytes > 0 THEN
  1891.             BEGIN
  1892.             BlankLine;
  1893.  
  1894.             FOR i := 0 TO (numBytes - 1) DIV 2 DO
  1895.                 BEGIN
  1896.                 addr := startAddress + i + i;
  1897.  
  1898.                 IF (i MOD 8) = 0 THEN
  1899.                     BEGIN
  1900.                     IF i > 0 THEN
  1901.                         BEGIN
  1902.                         PrintLine;
  1903.                         BlankLine;
  1904.                         END;
  1905.                     lineAddr := addr;                    { save the address for printline to use }
  1906.                     END;
  1907.  
  1908.                 decNumber := PInteger(addr)^;
  1909.                 FOR j := 4 DOWNTO 1 DO
  1910.                     BEGIN
  1911.                     numeric[numPos + j] := kHexDigits[BAND(decNumber, 15) + 1];
  1912.                     decNumber := BSR(decNumber, 4);
  1913.                     END;
  1914.  
  1915.                 decNumber := PInteger(addr)^;
  1916.                 FOR j := 2 DOWNTO 1 DO
  1917.                     BEGIN
  1918.                     chCode := BAND(decNumber, 255);
  1919.                     IF (chCode < $20) | (chCode > $D8) | (chCode = $7F) THEN { control, unassigned,
  1920.                            or DEL }
  1921.                         chCode := ord('•');
  1922.                     ascii[ascPos + j] := CHR(chCode);
  1923.                     decNumber := BSR(decNumber, 8);
  1924.                     END;
  1925.  
  1926.                 numPos := numPos + 5;
  1927.                 ascPos := ascPos + 2;
  1928.                 END;
  1929.  
  1930.             PrintLine;
  1931.             END;
  1932.         END;
  1933.  
  1934.     BEGIN
  1935.     theHandle := Handle(fObject);
  1936.     ShowMemory(StripLong(theHandle^), GetHandleSize(theHandle));
  1937.     END;
  1938.  
  1939. {---------------------------------------------------------------------------}
  1940.  
  1941. PROCEDURE TObjectView.InspectTEHandle(PROCEDURE InspectField(fieldName: StringPtr;
  1942.                                                              fieldAddr: Ptr;
  1943.                                                              fieldType: INTEGER));
  1944.  
  1945.     VAR
  1946.         hTE:                TEHandle;
  1947.         wasLocked:            BOOLEAN;
  1948.  
  1949.     BEGIN
  1950.     wasLocked := IsHandleLocked(Handle(hTE));
  1951.     LockHandleHigh(Handle(hTE));
  1952.  
  1953.     hTE := TEHandle(fObject);
  1954.     WITH hTE^^ DO
  1955.         BEGIN
  1956.         InspectField(AtStr('destRect'), @destRect, bRect);
  1957.         InspectField(AtStr('viewRect'), @viewRect, bRect);
  1958.         InspectField(AtStr('selRect'), @selRect, bRect);
  1959.         InspectField(AtStr('lineHeight'), @lineHeight, bInteger);
  1960.         InspectField(AtStr('fontAscent'), @fontAscent, bInteger);
  1961.         InspectField(AtStr('selPoint'), @selPoint, bPoint);
  1962.         InspectField(AtStr('selStart'), @selStart, bInteger);
  1963.         InspectField(AtStr('selEnd'), @selEnd, bInteger);
  1964.         InspectField(AtStr('active'), @active, bInteger);
  1965.         InspectField(AtStr('wordBreak'), @wordBreak, bPointer);
  1966.         InspectField(AtStr('clikLoop'), @clikLoop, bPointer);
  1967.         InspectField(AtStr('clickTime'), @clickTime, bLongInt);
  1968.         InspectField(AtStr('clickLoc'), @clickLoc, bInteger);
  1969.         InspectField(AtStr('caretTime'), @caretTime, bLongInt);
  1970.         InspectField(AtStr('caretState'), @caretState, bInteger);
  1971.         InspectField(AtStr('just'), @just, bInteger);
  1972.         InspectField(AtStr('teLength'), @teLength, bInteger);
  1973.         InspectField(AtStr('hText'), @hText, bHandle);
  1974.         InspectField(AtStr('recalBack'), @recalBack, bInteger);
  1975.         InspectField(AtStr('recalLines'), @recalLines, bInteger);
  1976.         InspectField(AtStr('clikStuff'), @clikStuff, bHexInteger);
  1977.         InspectField(AtStr('crOnly'), @crOnly, bInteger);
  1978.   {If txSize is -1 then the txFont and txFace fields are replaced
  1979.    by a handle to a style record.  See Inside Mac Vol. 5.}
  1980.         IF txSize = - 1 THEN
  1981.             InspectField(AtStr('txFont,txFace'), @txFont, bHandle)
  1982.         ELSE
  1983.             BEGIN
  1984.             InspectField(AtStr('txFont'), @txFont, bInteger);
  1985.             InspectField(AtStr('txFace'), @txFace, bStyle);
  1986.             END;
  1987.         InspectField(AtStr('txMode'), @txMode, bInteger);
  1988.         InspectField(AtStr('txSize'), @txSize, bInteger);
  1989.         InspectField(AtStr('inPort'), @inPort, bGrafPtr);
  1990.         InspectField(AtStr('highHook'), @highHook, bPointer);
  1991.         InspectField(AtStr('caretHook'), @caretHook, bPointer);
  1992.         InspectField(AtStr('nLines'), @nLines, bInteger);
  1993.         END;
  1994.     
  1995.     IF NOT wasLocked THEN
  1996.         HUnlock(Handle(hTE));
  1997.     END;
  1998.  
  1999. {---------------------------------------------------------------------------}
  2000.  
  2001. PROCEDURE TObjectView.InspectWindowPtr(PROCEDURE InspectField(fieldName: StringPtr;
  2002.                                                               fieldAddr: Ptr;
  2003.                                                               fieldType: INTEGER));
  2004.  
  2005.     VAR
  2006.         theWindow:            WindowPeek;
  2007.  
  2008.     BEGIN
  2009.     InspectGrafPtr(InspectField);
  2010.     theWindow := WindowPeek(fObject);
  2011.     WITH theWindow^ DO
  2012.         BEGIN
  2013.         InspectField(AtStr('windowKind'), @windowKind, bInteger);
  2014.         InspectField(AtStr('visible'), @visible, bBoolean);
  2015.         InspectField(AtStr('hilited'), @hilited, bBoolean);
  2016.         InspectField(AtStr('goAwayFlag'), @goAwayFlag, bBoolean);
  2017.         InspectField(AtStr('spareFlag'), @spareFlag, bBoolean);
  2018.         InspectField(AtStr('strucRgn'), @strucRgn, bRgnHandle);
  2019.         InspectField(AtStr('contRgn'), @contRgn, bRgnHandle);
  2020.         InspectField(AtStr('updateRgn'), @updateRgn, bRgnHandle);
  2021.         InspectField(AtStr('windowDefProc'), @windowDefProc, bHandle);
  2022.         InspectField(AtStr('dataHandle'), @dataHandle, bHandle);
  2023.         InspectField(AtStr('titleHandle'), @titleHandle, bHandle);
  2024.         InspectField(AtStr('titleWidth'), @titleWidth, bInteger);
  2025.         InspectField(AtStr('controlList'), @controlList, bControlHandle);
  2026.         InspectField(AtStr('nextWindow'), @nextWindow, bWindowPtr);
  2027.         InspectField(AtStr('windowPic'), @windowPic, bHandle);
  2028.         InspectField(AtStr('refCon'), @refCon, bHexLongInt);
  2029.         END;
  2030.     END;
  2031.  
  2032. {---------------------------------------------------------------------------}
  2033.  
  2034. PROCEDURE TObjectView.ChangeSelection(index: INTEGER;
  2035.                                       highlight: BOOLEAN); OVERRIDE;
  2036.  
  2037.     BEGIN
  2038.     SelectField(index, fInspectWindow);
  2039.     END;
  2040.  
  2041. {---------------------------------------------------------------------------}
  2042.  
  2043. PROCEDURE TObjectView.SelectField(index: INTEGER;
  2044.                                   inspectWindow: TInspectWindow);
  2045.  
  2046.     VAR
  2047.         fieldNo:            INTEGER;
  2048.  
  2049.     FUNCTION TestField(fieldName: StringPtr;
  2050.                        fieldAddr: Ptr;
  2051.                        fieldType: INTEGER): BOOLEAN;
  2052.  
  2053.         BEGIN
  2054.         fieldNo := fieldNo + 1;
  2055.         IF fieldNo = index THEN
  2056.             BEGIN
  2057.             CASE fieldType OF
  2058.                 bObject:
  2059.                     IF IsObject(TObjectPtr(fieldAddr)^) THEN
  2060.                         inspectWindow.SelectObject(TObjectPtr(fieldAddr)^, fieldType);
  2061.                 bGrafPtr, bWindowPtr, bTEHandle, bControlHandle, bRgnHandle, bHandle:
  2062.                     BEGIN
  2063.                     IF Handle(fieldAddr)^ <> NIL THEN
  2064.                         inspectWindow.SelectObject(TObjectPtr(fieldAddr)^, fieldType);
  2065.                     END;
  2066.             END;
  2067.             TestField := TRUE;
  2068.             END
  2069.         ELSE
  2070.             TestField := False;
  2071.         END;
  2072.  
  2073.     BEGIN
  2074.     IF (index > 0) & (index <= fNumberOfItems) THEN
  2075.         BEGIN
  2076.         fieldNo := 1;                                    { Skip title line }
  2077.         LockObject;
  2078.         FirstFieldThat(TestField);
  2079.         UnlockObject;
  2080.         END;
  2081.     END;
  2082.  
  2083. {--------------------------------------------------------------------------------------------------}
  2084.  
  2085. FUNCTION TObjectView.DoMouseCommand(VAR theMouse: Point;
  2086.                                     VAR info: EventInfo;
  2087.                                     VAR hysteresis: Point): TCommand; OVERRIDE;
  2088.  
  2089.     VAR
  2090.         index:                INTEGER;
  2091.         theVMouse:            VPoint;
  2092.         newInspectWindow:    TInspectWindow;
  2093.         wasAddNewObjectsToInspector: BOOLEAN;
  2094.  
  2095.     BEGIN
  2096.     IF info.theOptionKey THEN
  2097.         BEGIN
  2098.         QDToViewPt(theMouse, theVMouse);
  2099.         index := VPointToItem(theVMouse);
  2100.         IF (index > 0) & (index <= fNumberOfItems) THEN
  2101.             BEGIN
  2102.             {$IFC NOT qDebugTheDebugger}
  2103.             wasAddNewObjectsToInspector := AddNewObjectsToInspector(False);
  2104.             {$ENDC}
  2105.             newInspectWindow := pInspector.MakeWindow;
  2106.             {$IFC NOT qDebugTheDebugger}
  2107.             wasAddNewObjectsToInspector := AddNewObjectsToInspector(wasAddNewObjectsToInspector);
  2108.             {$ENDC}
  2109.  
  2110.             SelectField(index, newInspectWindow);
  2111.             newInspectWindow.Open;
  2112.             END;
  2113.         DoMouseCommand := NIL;
  2114.         END
  2115.     ELSE
  2116.         DoMouseCommand := INHERITED DoMouseCommand(theMouse, info, hysteresis);
  2117.     END;
  2118.  
  2119. {--------------------------------------------------------------------------------------------------}
  2120.  
  2121. PROCEDURE TObjectView.Draw(area: Rect); OVERRIDE;
  2122.  
  2123.     VAR
  2124.         fieldNo, firstField, lastField: INTEGER;
  2125.         viewArea:            VRect;
  2126.         baseVPoint:         VPoint;
  2127.         basePoint:            Point;
  2128.         aString:            Str255;
  2129.  
  2130.     PROCEDURE FitString(VAR theString: Str255;
  2131.                         maxWidth: INTEGER);
  2132.     { Truncates theString to fit in maxWidth pixels }
  2133.  
  2134.         VAR
  2135.             currWidth:            INTEGER;
  2136.             noOfChars:            INTEGER;
  2137.  
  2138.         BEGIN
  2139.         IF StringWidth(theString) > maxWidth THEN
  2140.             BEGIN
  2141.             currWidth := CharWidth('…');
  2142.             noOfChars := 0;
  2143.             REPEAT
  2144.                 noOfChars := noOfChars + 1;
  2145.                 currWidth := currWidth + CharWidth(theString[noOfChars]);
  2146.             UNTIL currWidth > maxWidth;
  2147.  
  2148.             {$Push} {$R-}
  2149.             theString[0] := CHR(noOfChars);             { Set length of theString }
  2150.             {$Pop}
  2151.             theString[noOfChars] := '…';
  2152.             END;
  2153.         END;
  2154.  
  2155.     PROCEDURE GetTitle(VAR aString: Str255);
  2156.  
  2157.         VAR
  2158.             typeName:            Str255;
  2159.             aStringPtr:         MANamePtr;
  2160.  
  2161.         BEGIN
  2162.         CASE fType OF
  2163.             bObject:
  2164.                 BEGIN
  2165.                 aStringPtr := MANamePtr(@typeName);
  2166.                 fObject.GetClassName(aStringPtr^);
  2167.                 END;
  2168.             bGrafPtr:
  2169.                 typeName := 'GrafPtr:';
  2170.             bWindowPtr:
  2171.                 typeName := 'WindowPtr:';
  2172.             bControlHandle:
  2173.                 typeName := 'ControlHandle:';
  2174.             bRgnHandle:
  2175.                 typeName := 'RgnHandle:';
  2176.             bTEHandle:
  2177.                 typeName := 'TEHandle:';
  2178.             bHandle:
  2179.                 typeName := 'Handle:';
  2180.         END;
  2181.         PointerToHex(ORD4(fObject), aString, 6);
  2182.         aString := CONCAT(typeName, '  ', aString);
  2183.         IF fType = bObject THEN
  2184.             BEGIN
  2185.             typeName := '';
  2186.             fObject.GetInspectorName(typeName);
  2187.             aString := CONCAT(aString, '  ', typeName);
  2188.             END;
  2189.         END;
  2190.  
  2191.     FUNCTION DrawField(fieldName: StringPtr;
  2192.                        fieldAddr: Ptr;
  2193.                        fieldType: INTEGER): BOOLEAN;
  2194.  
  2195.         PROCEDURE DrawObject(theObject: TObject);
  2196.  
  2197.             VAR
  2198.                 s1:                 Str255;
  2199.                 aString:            Str255;
  2200.                 aStringPtr:         MANamePtr;
  2201.  
  2202.             BEGIN
  2203.             { $xxxxx: ClassName Inspectorname }
  2204.             PointerToHex(ORD4(theObject), s1, 6);
  2205.  
  2206.             aStringPtr := MANamePtr(@aString);
  2207.             theObject.GetClassName(aStringPtr^);
  2208.             s1 := CONCAT(s1, ': ', aString);
  2209.  
  2210.             aString := '';
  2211.             theObject.GetInspectorName(aString);
  2212.             s1 := CONCAT(s1, ' ', aString);
  2213.             DrawString(s1);
  2214.             END;
  2215.  
  2216.         BEGIN
  2217.         DrawField := False;
  2218.         fieldNo := fieldNo + 1;
  2219.         IF fieldNo >= firstField THEN
  2220.             BEGIN
  2221.             IF fieldNo > lastField THEN
  2222.                 BEGIN
  2223.                 DrawField := TRUE;
  2224.                 END
  2225.             ELSE
  2226.                 BEGIN
  2227.  
  2228.                 IF fieldType = bInternalString THEN
  2229.                     BEGIN
  2230.                     MoveTo(4, basePoint.v);
  2231.                     DrawString(StringPtr(fieldAddr)^);
  2232.                     END
  2233.                 ELSE
  2234.                     BEGIN
  2235.                     IF fieldType = bClass THEN
  2236.                         BEGIN
  2237.                         aString := fieldName^;
  2238.                         TextFace([underline]);
  2239.                         END
  2240.                     ELSE
  2241.                         BEGIN
  2242.                         aString := CONCAT('   ', fieldName^, ': ');
  2243.                         FitString(aString, Max(94, BSR(fSuperView.fSize.h, 1)));
  2244.                         END;
  2245.  
  2246.                     MoveTo(4, basePoint.v);
  2247.                     DrawString(aString);
  2248.                     TextFace([]);
  2249.  
  2250.                     IF fieldType <> bClass THEN
  2251.                         FieldToString(fieldAddr, fieldType, aString)
  2252.                     ELSE
  2253.                         aString := '';
  2254.  
  2255.                     CASE fieldType OF
  2256.                         bObject, bGrafPtr, bWindowPtr, bControlHandle, bRgnHandle, bTEHandle,
  2257.                         bHandle:
  2258.                             IF Handle(fieldAddr)^ <> NIL THEN
  2259.                                 TextFace([bold]);
  2260.                     END;
  2261.  
  2262.                     MoveTo(Max(100, BSR(fSuperView.fSize.h, 1) + 4), basePoint.v);
  2263.                     IF (fieldType = bObject) & IsObject(TObjectPtr(fieldAddr)^) THEN
  2264.                         DrawObject(TObjectPtr(fieldAddr)^)
  2265.                     ELSE
  2266.                         DrawString(aString);
  2267.                     END;
  2268.                 TextFace([]);
  2269.                 basePoint.v := basePoint.v + fItemHeight;
  2270.                 END;
  2271.             END;
  2272.         END;
  2273.  
  2274.     BEGIN
  2275.     IF fObject <> NIL THEN
  2276.         BEGIN
  2277.         SetPen;
  2278.         QDToViewRect(area, viewArea);
  2279.         WITH viewArea DO
  2280.             BEGIN
  2281.             {adjust for QuickDraw geometry}
  2282.             bottom := bottom - 1;
  2283.             right := right - 1;
  2284.  
  2285.             firstField := top DIV fItemHeight + 1;
  2286.             lastField := Min(fNumberOfItems, bottom DIV fItemHeight + 1);
  2287.             END;
  2288.  
  2289.         SetVPt(baseVPoint, 4, IntMultiply(firstField - 1, fItemHeight) + fLineAscent);
  2290.         basePoint := ViewToQDPt(baseVPoint);
  2291.  
  2292.         IF firstField = 1 THEN
  2293.             BEGIN
  2294.             GetTitle(aString);
  2295.             MoveTo(basePoint.h, basePoint.v);
  2296.             DrawString(aString);
  2297.             basePoint.v := basePoint.v + fItemHeight;
  2298.             END;
  2299.  
  2300.         fieldNo := 1;                                    { Skip title line }
  2301.         LockObject;
  2302.         FirstFieldThat(DrawField);
  2303.         UnlockObject;
  2304.         END;
  2305.  
  2306.     INHERITED Draw(area);
  2307.     END;
  2308.  
  2309. {---------------------------------------------------------------------------}
  2310.  
  2311. PROCEDURE TObjectView.SuperViewChangedSize(delta: VPoint;
  2312.                                      invalidate: BOOLEAN);
  2313.  
  2314.     BEGIN
  2315.     IF invalidate THEN
  2316.         ForceRedraw;
  2317.     INHERITED SuperViewChangedSize(delta, invalidate);
  2318.     END;
  2319.  
  2320. {---------------------------------------------------------------------------}
  2321.  
  2322. PROCEDURE TObjectView.Resize(width, height: VCoordinate;
  2323.                              invalidate: BOOLEAN); OVERRIDE;
  2324.  
  2325.     BEGIN
  2326.     IF invalidate & ((fSize.h <> width) | (fSize.v <> height)) THEN
  2327.         ForceRedraw;
  2328.     INHERITED Resize(width, height, invalidate);
  2329.     END;
  2330.  
  2331. {---------------------------------------------------------------------------}
  2332. PROCEDURE TObjectView.FirstFieldThat(FUNCTION TestField(fieldName: StringPtr;
  2333.                                                         fieldAddr: Ptr;
  2334.                                                         fieldType: INTEGER): BOOLEAN);
  2335.  
  2336.     LABEL 1000;
  2337.  
  2338.     VAR
  2339.         oldState:            BOOLEAN;
  2340.         fi:                 FailInfo;
  2341.  
  2342.     PROCEDURE HandleFailure(error: INTEGER;
  2343.                             message: LONGINT);
  2344.  
  2345.         BEGIN
  2346.         IF error = 0 THEN
  2347.             GOTO 1000
  2348.         ELSE                                            { someone else signalled it, just let it
  2349.                                                          propagate. }
  2350.             BEGIN
  2351.             {$IFC qDebug}
  2352.             gIntenseDebugging := oldState;
  2353.             {$EndC}
  2354.             END;
  2355.         END;
  2356.  
  2357.     PROCEDURE DoToField(fieldName: StringPtr;
  2358.                         fieldAddr: Ptr;
  2359.                         fieldType: INTEGER);
  2360.  
  2361.         BEGIN
  2362.         IF TestField(fieldName, fieldAddr, fieldType) THEN
  2363.             Failure(0, 0);                                { this is kinder to .Fields methods that
  2364.                                                          would quiver when a simple exit would yank
  2365.                                                          the rug out from under them }
  2366.         END;
  2367.  
  2368.     PROCEDURE DoToObjectField(fieldName: Str255;
  2369.                         fieldAddr: Ptr;
  2370.                         fieldType: INTEGER);
  2371.         { The Str255 datatype is required to match the fieldName parameter that the procedure
  2372.         parameter to fields methods requires.  In some future version of MacApp it would be nice
  2373.         to switch .Fields methods to take StringPtrs or maybe to just backend this proc with a
  2374.         procedure that takes StringPtrs but trick the compiler into taking it.  Remember that
  2375.         C++ users also get to suffer with whatever ultimate solution is chosen. }
  2376.  
  2377.         BEGIN
  2378.         IF TestField(@fieldName, fieldAddr, fieldType) THEN
  2379.             Failure(0, 0);                                { this is kinder to .Fields methods that
  2380.                                                          would quiver when a simple exit would yank
  2381.                                                          the rug out from under them }
  2382.         END;
  2383.  
  2384.     BEGIN
  2385.     {$IFC qDebug}
  2386.     oldState := gIntenseDebugging;
  2387.     gIntenseDebugging := False;                         { Suppress printing of info from failure
  2388.                                                          signals }
  2389.     {$EndC}
  2390.  
  2391.     CatchFailures(fi, HandleFailure);
  2392.     CASE fType OF
  2393.         bObject:
  2394.             fObject.Fields(DoToObjectField);
  2395.         bGrafPtr:
  2396.             InspectGrafPtr(DoToField);
  2397.         bWindowPtr:
  2398.             InspectWindowPtr(DoToField);
  2399.         bControlHandle:
  2400.             InspectControlHandle(DoToField);
  2401.         bRgnHandle:
  2402.             InspectRgnHandle(DoToField);
  2403.         bTEHandle:
  2404.             InspectTEHandle(DoToField);
  2405.         bHandle:
  2406.             InspectHandle(DoToField);
  2407.     END;
  2408.     Success(fi);
  2409.  
  2410. 1000:
  2411.     {$IFC qDebug}
  2412.     gIntenseDebugging := oldState;
  2413.     {$EndC}
  2414.  
  2415.     END;
  2416.  
  2417. {---------------------------------------------------------------------------}
  2418.  
  2419. PROCEDURE TObjectView.Fields(PROCEDURE DoToField(fieldName: Str255;
  2420.                                                  fieldAddr: Ptr;
  2421.                                                  fieldType: INTEGER)); OVERRIDE;
  2422.  
  2423.     BEGIN
  2424.     DoToField('TObjectView', NIL, bClass);
  2425.     DoToField('fInspectWindow', @fInspectWindow, bObject);
  2426.     DoToField('fObject', @fObject, bObject);
  2427.     DoToField('fType', @fType, bInteger);
  2428.     DoToField('fLockState', @fLockState, bBoolean);
  2429.  
  2430.     INHERITED Fields(DoToField);
  2431.     END;
  2432.  
  2433. {---------------------------------------------------------------------------}
  2434.  
  2435. PROCEDURE TObjectView.InstallObject(theObject: TObject;
  2436.                                     theObjectType: INTEGER);
  2437.  
  2438.     VAR
  2439.         noOfFields:         INTEGER;
  2440.  
  2441.     FUNCTION CountField(fieldName: StringPtr;
  2442.                         fieldAddr: Ptr;
  2443.                         fieldType: INTEGER): BOOLEAN;
  2444.  
  2445.         BEGIN
  2446.         CountField := False;
  2447.         noOfFields := noOfFields + 1;
  2448.         END;
  2449.  
  2450.     BEGIN
  2451.     fObject := theObject;
  2452.     fType := theObjectType;
  2453.     noOfFields := 1;                                    { Includes 1 line for title }
  2454.     IF theObject <> NIL THEN
  2455.         BEGIN
  2456.         LockObject;
  2457.         FirstFieldThat(CountField);
  2458.         UnlockObject;
  2459.         END;
  2460.     SetNumberOfItems(noOfFields);
  2461.     RevealTop(kDontRedraw);
  2462.     END;
  2463.  
  2464. {---------------------------------------------------------------------------}
  2465.  
  2466. PROCEDURE TObjectView.LockObject;
  2467.  
  2468.     BEGIN
  2469.     IF fType = bObject THEN
  2470.         fLockState := fObject.Lock(TRUE)
  2471.     ELSE IF (fType = bHandle) | (fType = bTEHandle) | (fType = bControlHandle) | (fType =
  2472.             bRgnHandle) THEN
  2473.         BEGIN
  2474.         fLockState := IsHandleLocked(fObject);
  2475.         IF NOT fLockState THEN
  2476.             HLock(Handle(fObject));
  2477.         END;
  2478.     END;
  2479.  
  2480. {---------------------------------------------------------------------------}
  2481.  
  2482. PROCEDURE TObjectView.UnlockObject;
  2483.  
  2484.     VAR
  2485.         oldState:            BOOLEAN;
  2486.  
  2487.     BEGIN
  2488.     IF fType = bObject THEN
  2489.         oldState := fObject.Lock(fLockState)
  2490.     ELSE IF (fType = bHandle) | (fType = bTEHandle) | (fType = bControlHandle) | (fType =
  2491.             bRgnHandle) THEN
  2492.         IF NOT fLockState THEN
  2493.             HUnLock(Handle(fObject));
  2494.     END;
  2495.